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:
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.
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 parent
activity`
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