Android MVP - How to communicate between activity presenter and fragment presenter

Norutan picture Norutan · Apr 19, 2016 · Viewed 8k times · Source

I have an activity with 3 fragments, currently I use ViewPager. I want to implement MVP and communicate between activity presenter and fragment presenters i.e:

  • Passing data from activity presenter to fragment presenters
  • Sending event from fragment presenters to activity presenter
  • ...

But I don't know how to do it in official way. I can use BusEvent but I don't think it's a good practice.

Answer

sutuioncode picture sutuioncode · Apr 7, 2019

Communication between fragments and activity or vice-versa can be done by using nnn's answer or you could use ViewModel and LiveData witch provides a cleaner way and respect the lifecycle from fragments and activities which can save from writing a few lines of code in attempt to prevent a a non-visible fragment from receiving data on the background.

First you extend the ViewModel class, initialize the Livedata and some helper methods.

public class MyViewModel extends ViewModel {
private MutableLiveData<String> toFragmentA, toFragmentB;
private MutableLiveData<List<String>>  toAllFragments;

public MyViewModel() {
    toFragmentA = new MutableLiveData<>();
    toFragmentB = new MutableLiveData<>();
    toAllFragments = new MutableLiveData<>();
}

public void changeFragmentAData(String value){
    toFragmentA.postValue(value);
}
public void changeFragmentBData(String value){
    toFragmentB.postValue(value);
}
public void changeFragmentAllData(List<String> value){
    toAllFragments.postValue(value);
}

public LiveData<String> getToFragmentA() {
    return toFragmentA;
}

public LiveData<List<String>> getToAllFragments() {
    return toAllFragments;
}

public LiveData<String> getToFragmentB() {
    return toFragmentB;
}

}

Then you initialize the ViewModel on your activity.

public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private TabLayout tabLayout;
MyViewModel mViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mViewModel = ViewModelProviders.of(this)
            .get(MyViewModel.class);

    viewPager.setAdapter(new Adapter(getSupportFragmentManager()));


}

}

reading the data in the fragments:

 @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

    mViewModel.getToAllFragments().observe(this, new Observer<List<String>>() {
        @Override
        public void onChanged(List<String> s) {
            myList.addAll(s);
            //do something like update a RecyclerView
        }
    });

    mViewModel.getToFragmentA().observe(this, new Observer<String>() {


        @Override
        public void onChanged(String s) {
            mytext = s;
            //do something like update a TextView
        }
    });
}

to change the values of any of the live datas you can use one of the methods in any of the fragments or in the activity:

changeFragmentAData();
changeFragmentBData();
changeFragmentAllData();

Whats happing behind the scenes:

when you use mViewModel = ViewModelProviders.of(this).get(MyViewModel.class) you are creating a n instance of ViewModel and binding it to the lifecycle of the given activity of fragment so the view model is destroid only the the activity or fragement is stopped. if you use mViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class)you are bindig it to the lifecycle if the parentactivity`

when you use mViewModel.getToFragmentA().observe() or mViewModel.getToFragmentB().observe() or mViewModel.getToAllFragments().observe() you are connecting the LiveData in MyViewModel class to the given fragment or activity an the value of the onChange() method is updated in all the classes that are observing the method.

I recomend for personal expirience a bit of research about Livedata end ViewModel which ou can on youtube or this link