Search code examples
androidretrofitmvpmosby

Android MVP - screen orientation - retain presenters state


I have a question regarding MVP pattern in Android. I want to write my own "application core" which will have base classes for presenters, views etc. It has to be simple, clean and "stable". My idea is very similiar to what Mosby has to offer, I'm trying to achive something like this:

  1. Each Activity has it's own Presenter, View (interface to communicate with Activity), ViewState (parcelable object that holds persistent data).
  2. When Activity is being destroyed:

    • detach View
    • save ViewState in bundle
    • cancel all background tasks in Presenter (tasks that updates View when finished)
    • destroy Presenter
  3. When Activity is being recreated:

    • attach View
    • restore ViewState
    • create new instance of Presenter
    • restart background tasks that have been canceled

I've got almost eveything done except that last issue - "restart background tasks that has been canceled". It will be easier to discuss it with an example. So let's say I have two methods in a presenter (Retrofit 2 calls):

  • downloadUsers() - fetches users data from web server and onSuccess updates view
  • downloadProject() - fetches project info from web server and onSuccess updates view

Now user is changing configuration when one of those calls has been started but not finished yet. How will I know which one of them I should restart when Presenter will be recreated?

The only idea that comes to my mind is create a persitent boolean flag for each task, set it true when task is starting, and false when it is finished. When Presenter will be created I will check every flag and restart corresponding calls.

What do you think about it? How it can be improved? Any other ideas?


Solution

  • I don't know how your UI looks like, but to me it sounds that you should split your one big View into two subviews:

    • DownloadUsersView + ViewState managed by a DownloadUsersPresenter
    • DownloadProjectsView + ViewState managed by a DownloadProjectsPresenter

    From my point of view it is always a good idea that MVP has exactly one single Model that gets displayed in the View (and not two like in your scenario). Usually if you have to deal with two models in the same view it is a indicator that you can split this view and presenter into two distinct.

    Alternatively, you can merge your two models into one single Model, saying

    class DownloadModel {
      List<User> users;
      List<Project> projects;
    }
    

    and then you combine your two Retrofit calls to create a DownloadModel and when both calls are completed you can display the DownloadModel inside your view. With retrofit and rxjava this is quite simple (see combineLatest() operator). In that case you don't have that problem because your Presenter only has one download() methods which downloads both in parallel. If one is significant faster then the other, then it's very likely that after orientation changes and recreation of the presenter the faster one comes from retrofit cache so this shouldn't bother you to much.

    As you have already said you could also start keeping track in the presenter which http call was executing before and reinvoke them once the presenter gets re-instantiated, but that means that the presenter has to save it's internal state as well into the bundle. Mosby don't make any specification about that and assumes that in general there is no such need. Hence Mosby's default Presenter implementation doesn't provide a presenter.saveInstanceState(Bundle) and presenter.restoreInstanceState(Bundle). But that doesn't mean that you can not / should not do that. You can do that in Mosby and in your implementation as well. However, if you start doing so then you just move the spaghetti code previously (without mvp) sitting in the Activity class into the presenter.

    Therefore, once again, I strongly recommend to have one single model per view in MVP.

    Btw. why reinventing the wheel? Sounds like Mosby is already providing the things you are looking for. Mosby also supports retaining presenter which are surviving screen orientation changes.