Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

android

mvp

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.

like image 305
Norutan Avatar asked Apr 19 '16 03:04

Norutan


People also ask

How can fragment and activity communicate with each other?

In order to allow fragments and activities to communicate we need to capture an instance of our interface and cast it into the context of the activities we need to communicate with. Thankfully, we can do this in something called the onAttach() method.

What is presenter in MVP Android?

Example of MVP Architecture The role of the Presenter class is to keep the business logic of the application away from the activity. Below is the complete step-by-step implementation of this android application. Note that we are going to implement the project using both Java and Kotlin language.


2 Answers

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

like image 193
sutuioncode Avatar answered Oct 06 '22 11:10

sutuioncode


As per my understanding, for your UseCase, suppose ActivityA have a viewPager having 3 Fragments(FragmentA, FragmentB, FragmentC).

ActivityA have ActivityPresenterA

FragmentA have FragmentPresenterA

As per MVP, FragmentPresenterA should be responsible for all the logical and business flows of FragmentA only and should communicate with FragmentA only. Therefore, FragmentPresenterA can not directly communicate with ActivityPresenterA.

For communication from Fragment to Activity, presenter should not be involved and this should be done as we would communicate in non-MVP architecture, i.e. with the help of interface.

Same applies for Activity to Fragment communication.

For communication between Activity and Fragment read here

like image 34
nnn Avatar answered Oct 06 '22 12:10

nnn