Lifecycle aware Presenter instead of LiveData

Michał Pawlik
ProAndroidDev
Published in
4 min readAug 22, 2018

--

Source: https://goo.gl/VknZwA

Architecture Components (AC) brought us LiveData, a lifecycle-aware observable data holder class - the idea is great and sounds super handy. The thing is, once we start using it multiple problems emerge:

Additional code

  • onChanged parameter in Observer interface is annotated as @Nullable so we must always handle null case in our onChanged implementation, even though we might have specified type of data held by our LiveData as @NonNullable. We must either always handle this explicitly or create some kind of workaround eg. nonNullObserve
  • while retrieving data we usually want to notify our Observers when loading started or error occurred, so… we end up with next workaround by creating some kind of Resource class
  • sometimes we want data to be consumed only once, like a SnackBar message or Dialog trigger, hence SingleLiveEvent or Event wrappers
  • observing in Fragments, due to their lolcycle we ended up with getLifecycle for Fragment’s lifecycle and getViewLifecycleOwner for Fragment’s View lifecycle, to avoid accidentally setting second observer

Maintainability

  • It’s harder to read and understand the flow in the code — instead of simple View Presenter View communication like he have in MVP, we now have a callbacks chain View ViewModel LiveData Resource View
  • Using LiveData with Resource means making our Views hold logic for reacting to different states, which might be fine from perspective of reactive architecture, but not desired from a Passive View pattern as it makes our Views less dumb
  • If some part of View’s state depends on 2 or more types of data, we either have to create next class to wrap all of them or place logic for retrieving them from LiveData and properly reacting in View
  • We cannot (JUnit) test if the right view’s method with right value was called, but only if the right value was propagated. Which also means that we cannot test if the view changes it’s state correctly

Hmm…

I’m not trying to say that these are huge issues or that we should stop using LiveData because we have to create a couple of extra classes or write more code, but it seems like we simply don’t need all that for most of the time.

AC also brought Lifecycle, for building lifecycle-aware components and ViewModel, which except for its misleading name, turned out to be very practical.

Hence lifecycle-aware Presenter

First let’s create a BasePresenter class:

A couple of things are happening here:

  • Presenter extending ViewModel might seem weird, but let’s not confuse it with ViewModel from MVVM - ViewModel in AC is “designed to store and manage UI-related data in a lifecycle conscious way”, which is exactly what we want to achieve
  • Thanks to extending ViewModel the Presenter instance will survive configuration changes
  • Thanks to passing and observing viewLifecycle every Presenter will automatically set it’s view reference to null before the view gets destroyed
  • view field is encapsulated and access to it is only possible via view() call in derived classes

Note

Similarly to ViewModels we should create instances of derived Presenters via ViewModelProvider and similarly to observing LiveData we should pass lifecycle from getLifecycle() in Activities and lifecycle from getViewLifecycleOwner() in Fragments when calling attachView()

Simple example of usage

View interface:

Presenter implementation:

Edit: Some people pointed out that loadMovies() is called after every configuration change, and it’s true, but the network request is made only once, because data is cached by Repository. I made it in this way in this example, but depending on the needs, we could also store reference to the data in Presenter.

PresenterFactory implementation:

I’m using here Dagger Providers to avoid creating new instances of dependencies after every configuration change.

View implementation:

And that’s it.
Good, old MVP, with automatic detaching and advantages of ViewModel.

Benefits of Lifecycle aware MVP

  • simple, addressing both lifecycle and configuration changes problems
  • clear and explicit View actions, like in classic MVP, which allows us to easier manage changes in the View
  • no LiveData, no Resource’s state handling in Activities or Fragments
  • thanks to directly communicating with the view it’s easier to pass any necessary parameters straight to view methods
  • if you have existing MVP architecture and want to make use of ViewModels and their handling of configuration changes, this is an easy way to do achieve it

Additional resources

Final words

As common as it is, I’m not gonna tell you that this is the only right architecture and you should start using it right away. Use whatever works best for you.

This is a pattern I find very useful and handy due to all above-mentioned benefits. What I personally like the most about it, is the synergy between MVP and Architecture Components, taking the simplicity of Presenter and smartness of Lifecycle.

--

--