android - Pass data from Activity to Fragment in ViewPager

29,774

Solution 1

Okay, I did this.

1 step: I created public interface in my Activity and setter for it:

private OnAboutDataReceivedListener mAboutDataListener;

public interface OnAboutDataReceivedListener {
        void onDataReceived(AboutCompanyViewModel model);
    }

public void setAboutDataListener(OnAboutDataReceivedListener listener) {
    this.mAboutDataListener = listener;
}

2 step: I implemented this interface in my Fragment and set listener:

public class AboutCompanyFragment extends BaseFragment implements ManagementCompanyOverviewActivity.OnAboutDataReceivedListener

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mActivity = (ManagementCompanyOverviewActivity) getActivity();
            mActivity.setAboutDataListener(this);
        }

3 step: I overrided interface's method:

@Override
    public void onDataReceived(AboutCompanyViewModel model) {
        mPBName.setVisibility(View.INVISIBLE);
        mPBDirector.setVisibility(View.INVISIBLE);
        mPBWebsite.setVisibility(View.INVISIBLE);
        mPBEmail.setVisibility(View.INVISIBLE);
        mPBPhone.setVisibility(View.INVISIBLE);
        mPBSchedule.setVisibility(View.INVISIBLE);
        mPBAddress.setVisibility(View.INVISIBLE);

        mTVName.setVisibility(View.VISIBLE);
        mTVDirector.setVisibility(View.VISIBLE);
        mTVWebsite.setVisibility(View.VISIBLE);
        mTVEmail.setVisibility(View.VISIBLE);
        mTVPhone.setVisibility(View.VISIBLE);
        mTVSchedule.setVisibility(View.VISIBLE);
        mTVAddress.setVisibility(View.VISIBLE);

        mTVName.setText(model.getCompanyName());
        mTVDirector.setText(model.getDirectorName());
        mTVWebsite.setText(model.getWebsite());
        mTVEmail.setText(model.getEmail());
        mTVPhone.setText(model.getPhone());
        mTVSchedule.setText(model.getWorkTime());
        mTVAddress.setText(model.getAddress());
    }

That's it.

Solution 2

Try this In activity

public String sendData() {
        return YOUR_STRING;
    }

In Fragment

YOUR_ACTIVITY activity = (YOUR_ACTIVITY) getActivity();
String getData = activity.SendData();

Solution 3

You can use newInstance method in your Fragment:

public static MyFragment newInstance(String parameter) {

        Bundle args = new Bundle();
        args.putString("parameter", parameter);
        SfCategoryFragment fragment = new SfCategoryFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            parameter = getArguments().getString("parameter");
        }
    }

And in your Activity:

instead of new MyFragment() use MyFragment.newInstance("yourParam");

Solution 4

You could also in your adapter's constructor take in the data you want to display in the fragment and set the arguments before returning a new fragment

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Weather weather;

ViewPagerAdapter(FragmentManager fm, Weather weather) {
    super(fm);
    this.weather = weather;
}

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            Bundle bundle = new Bundle();
            WeatherFragment weatherFragment = new WeatherFragment();
            bundle.putParcelable("weather", weather);
            weatherFragment.setArguments(bundle);
            return weatherFragment;
        case 1:
            return new PoemFragment();
        default:
            return new EmptyFragment();
    }
}

Solution 5

From Activity or ViewPager

Bundle bundle = new Bundle();
bundle.putParcelable(Keys.KEY_ITEM, cardResult);
CardItemFragment cardItemFragment = new CardItemFragment();
cardItemFragment.setArguments(bundle);

From Fragment

@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     getBundle();
}


private void getBundle() {
    bundle = getArguments();
    if (null != bundle) {
        if (bundle.containsKey(Keys.KEY_ITEM)) {
            cardResult = bundle.getParcelable(Keys.KEY_ITEM);
        }
    }
}
Share:
29,774
Den
Author by

Den

BY DAY: Working as a Junior Android Developer :) Playing guitar with my band; Roller-skating; Playing video games. BY NIGHT: Sleeping :) Playing video-games ofc!

Updated on July 09, 2022

Comments

  • Den
    Den almost 2 years

    I have a simple Activity with TabLayout, ViewPager and 2 Fragments in it. Here's my Activity:

    public class ManagementCompanyOverviewActivity extends BaseActivity implements ManagementCompanyOverviewView {
    
        private ManagementCompanyVPAdapter mVPAdapter;
        private TabLayout mTLContent;
        private ViewPager mVPContent;
    
        @InjectPresenter
        ManagementCompanyPresenter mPresenter;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_management_company);
    
            mVPAdapter = new ManagementCompanyVPAdapter(getSupportFragmentManager());
    
            mTLContent = (TabLayout) findViewById(R.id.tl_company_content);
    
            mVPContent = (ViewPager) findViewById(R.id.vp_company_content);
            mVPContent.setAdapter(mVPAdapter);
            mTLContent.setupWithViewPager(mVPContent);
        }
    
        @Override
        public void onAboutCompanyInfoReceivedFromServer(AboutCompanyViewModel model) {
    
        }
    

    Activity has a Presenter (I'm using Moxy), Presenter sends request, gets answer, creates JavaObject (view model) and with getViewState() passes this model to activity. I need to pass this model from Activity to one of my Fragments.

    Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
        View view = inflater.inflate(R.layout.fragment_about_company, container, false);
    
        mTVName = (TextView) view.findViewById(R.id.tv_company_name);
        mTVDirector = (TextView) view.findViewById(R.id.tv_company_director);
        mTVWebsite = (TextView) view.findViewById(R.id.tv_company_website);
        mTVEmail = (TextView) view.findViewById(R.id.tv_company_email);
        mTVPhone = (TextView) view.findViewById(R.id.tv_company_phone);
        mTVSchedule = (TextView) view.findViewById(R.id.tv_company_schedule);
        mTVAddress = (TextView) view.findViewById(R.id.tv_company_address);
    
        return view;
    }
    

    This fragment has some TextViews to show the info from my model. How to pass this model? If I know it right I should create a listener, but how? I don't completely understand how to work with em.

  • Den
    Den over 6 years
    Nope, not gonna work. Data comes from the server and it can be received in 3-5 seconds. Method public void onAboutCompanyInfoReceivedFromServer(AboutCompanyViewModel model) is called when my Activity received this data.
  • Den
    Den over 6 years
    Activity should send data to fragment, when the data is ready. I can't use getter.
  • MKovac
    MKovac over 6 years
    You can try setupViewPager when you receive data, i did like that in my app
  • Den
    Den over 6 years
    Can you post some example code? Just edit your first answer :)
  • MKovac
    MKovac over 6 years
    I don't know where you are getting data. I'm using AsyncTask and when task is finished i call setupViewPager. Just put mTLContent.setupWithViewPager(mVPContent); to method where you get data response
  • Den
    Den over 6 years
    Well, this is not my case I guess. I need to init fragments from the start and show progress bars in every field till the data received.
  • MKovac
    MKovac over 6 years
    You can show progress bar until you don't receive data. I hope someone will have some other solution for you :)
  • Den
    Den almost 6 years
    Nope, my fragment is already running and I don't want to reinit it
  • hetsgandhi
    hetsgandhi over 5 years
    Thank you.It works in my case and saved much of my time!
  • Pinkesh Darji
    Pinkesh Darji over 5 years
    Thanks a lot. You saved my hours.
  • Masterpiece Mas Icang
    Masterpiece Mas Icang over 5 years
    how to assign AboutCompanyViewModel from activity?
  • Den
    Den over 5 years
    @MasterpieceMasIcang you just call your interface method and pass it.
  • Shivam Kumar
    Shivam Kumar over 5 years
    @Den Can you tell me how to set data from activity with example
  • Vishal Thakkar
    Vishal Thakkar almost 5 years
    @Den in my case i have to fragment in view pager and i have to pass that data in both fragment i was implemented this but it pass data in second fragment not in first fragment
  • Mr.Drew
    Mr.Drew over 4 years
    Does this break when the fragment gets replaced or destroyed?
  • M. H.
    M. H. over 3 years
    This code is working only if the fragment from the same activity .. if you change the activity this line will no longer be useful:- mActivity = (ManagementCompanyOverviewActivity) getActivity();
  • Den
    Den almost 3 years
    What if your Fragment is used in another Activity? You always should use interfaces to re-use your code.
  • Adnan Bashir
    Adnan Bashir almost 3 years
    You are 100% right but we are talking about data passing from activity to fragment , definitely if you need data in other activity which is not in running state then you must use Interfaces
  • Den
    Den almost 3 years
    Anyway, in my original post the case is the activity receives some data from the internet and this activity should send this data to fragments, getters will not help in this case.
  • Rajneesh Shukla
    Rajneesh Shukla over 2 years
    Hi, The new solution of this question is. If you are using MVVM then use a shared viewModel. Thanks!