Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVP for Activity with multiple Fragments

I have an Activity with two Fragments in it.

The activity (MainActivity) retrieves data from an open weather api. I have implemented MVP for this in which: Model contains all the response objects from the API
View is the Activity
Presenter contains MainPresenter, MainPresenterImpl, MainView, GetDataInteractor and GetDataInteractorImpl.

So, the activity gets the data from the web service. Both fragments will display data from the data retrieved in the activity.

What is the best practice using MVP in this situation? I know how to pass data between fragments <-> activity via interface/callbacks, my question is does this behaviour change when implementing MVP?

like image 541
DJ-DOO Avatar asked Dec 13 '15 23:12

DJ-DOO


People also ask

Can one activity have multiple fragments?

Fragments represent a small portion of the screen in an Activity. We can use one to multiple fragments in a single activity. Based on the app requirements, we might use fragments in our app or we might not use and cover the most of the screens using Activity classes.

How many fragments can there be in one activity?

Two Fragments should never communicate directly. Show activity on this post. There is no official guideline regarding the limit of fragments that can be added to an activity. You can have as many as you need and looks logical for your app.

What are fragments in Android activity?

According to the Android documentation, a fragment is a part of applications user interface that is bound to an activity. Fragments have their lifecycle and layouts or UI components. Fragments help enrich your UI design, pass data between different screens, and adapt to different device configurations.


1 Answers

The activity/fragments should be considered as just the view in the MVP model. This means that they should just show data and receive user interactions. It is ok to communicate activity and fragments via interface/callbacks.

But, it is not an activity/fragment responsibility to call the API services.

The presenter should be responsible to call the api services.

So, the presenter should expose a method like loadXXX, internally it would make the call to the service. When the response is received, the presenter should call view.showXXX with the results of the service. The activity/fragment should call this loadXXX method and implement the showXXX.

Usually, the presenter is created or injected into the activity/fragment. The activity/fragment has to implement an interface exposed by the presenter, and the presenter holds a weak reference of this interface, so that it can callback.

When the user interacts with the screen, for example, an onClick on a button, the activity/fragment calls the corresponding method in the presenter, e.g. presenter.loadUserDetails() the presenter tells the view to show as loading, e.g. view.showAsLoading() because it has to do its stuff: maybe validating something or loading data from an api service and finally callback with the results to the view, e.g. view.showUserDetails(userDetails).

To summarize, an example, in code of the various parts of MVP:

Activity/Fragment represents just the View of MVP:

public class MyActivity extends AppCompatActivity implements MyPresenter.View {     private MyPresenter mPresenter;      public onCreate() {         ...         mPresenter = new MyPresenter(this); // Or inject it and then set the view.     }      public void onClick(View v) {         mPresenter.loadXXX(param1, param2);     }      // MyPresenter.View methods      public void showAsLoading() {         ...     }      public void showUserDetails(UserDetails userDetails) {         ...     } } 

Model:

public class UserDetails {     ... } 

Presenter:

public class MyPresenter {      private WeakReference<MyPresenter.View> mWeakView;      public MyPresenter(MyPresenter.View view) {         mWeakView = new WeakReference(view);     }      public void loadXXX(String param1, String param2) {         MyPresenter.View view = mWeakView.get();         if (view != null) {             view.showAsLoading();             // Do stuff, e.g. make the Api call and finally call view.showUserDetails(userDetails);         }     }      interface View {         void showAsLoading();         void showUserDetails(UserDetails userDetails);     }  } 
like image 133
fernandospr Avatar answered Sep 22 '22 02:09

fernandospr