androidmvplifecycle

Android MVP and Lifecycle architecture component


I am trying to combine MVP with Lifecycle architecture component.

Well known that you should attach and detach VIEW from PRESENTER on start and stop to avoid memory leaks. But LifecycleOwner/LifecycleObserver cannot work if View is attached to Presenter...

For learning purposes I create simple (M)VP application, the View is attached and detached to Presenter in onStart() and onStop() methods. It works fine.

After that I convert Presenter to LifecycleObserver, subscribe it to LifecycleOwner events (LifecycleOwner is View) and remove onStart()/onStop() methods from View. In this case app crashes on startup.

View class (v1):

public class MyView extends AppCompatActivity {

    private final static String TAG = "myLogs";
    MyPresenter myPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "CREATE");
        setContentView(R.layout.activity_main);
        myPresenter = new MyPresenter();
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "START");
        myPresenter.linkView(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "STOP");
        myPresenter.unlinkView();
    }
}

Presenter class (v1):

class MyPresenter {

    private final static String TAG = "myLogs";
    MyView view;

    public void linkView(MyView v) {
        Log.d(TAG, "linkView()");
        this.view = v;
    }

    public void unlinkView() {
        Log.d(TAG, "unlinkView()");
        this.view = null;
    }
}

This works fine.

And then I try to add Lifecycle architecture component like so:

View class (v2):

public class MyView extends AppCompatActivity {

    private final static String TAG = "myLogs";
    MyPresenter myPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "CREATE");
        setContentView(R.layout.activity_main);
        myPresenter = new MyPresenter();
        getLifecycle().addObserver(myPresenter);
    }
}

Presenter class (v2):

class MyPresenter implements LifecycleObserver {

    private final static String TAG = "myLogs";
    MyView view;

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void linkView(MyView v) {
        Log.d(TAG, "linkView()");
        this.view = v;
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void unlinkView() {
        Log.d(TAG, "unlinkView()");
        this.view = null;
    }
}

Differences are:

1. I add "implements LifecycleObserver" to MyPresenter;
2. add start/stop annotations to MyPresenter methods;
3. remove onStart()/onStop() methods from MyView;
4. subscribe MyPresenter to MyView lifecycle events in onCreate() method.

Result:

As a result app crashes on startup with following error exception:

Unable to start activity MyView. Must be one and instanceof LifecycleOwner

The error goes out if not link View to Presenter. But it breaks down MVP pattern. So, can MVP pattern on Android be combined with Lifecycle?


Solution

  • You need to check if your Lifecycle is atleast in STARTED state,

    for solution, consider this code placing in your onStart() method after super() call:

    getLifecycle().addObserver(myPresenter);
    

    or you can pass LifeCycle object to your presenter & addObserver() itself there by checking condition:

     if (lifecycle.getCurrentState().isAtLeast(STARTED)) {
     // Do your stuff here
     }
    

    More from here & also check Lifecycle.States: