Android : Easier MVP with Lite-Cycle
Ahmed Adel Ismail
Engineering Manager @ Yassir | x-SadaPay | x-Swvl | x-Talabat | x-TryCarriage | x-Vodafone | More than a decade of experience in Android development and teams leadership
One of the major issues that we face in our Android applications is the Life-Cycle related events, and when we use an Architecture pattern like MVP, we have to put those Life-Cycle related events in the Presenter interface so we can update our data based on the Life-Cycle, And this is where Lite-Cycle helps eliminating this boilerplate code ... let us dig into code :
The Old Way
Suppose we have an Activity that displays the current location on Map, so we have the View interface as follows :
public interface MainView {
void updateLocationOnMap(Location location);
}
And this is our Activity that implements the View interface
public class MainActivity extends AppCompatActivity implements MainView{
private MainPresenter presenter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
presenter = new MainPresenterImplementer(this);
}
protected void onStart() {
super.onStart();
presenter.onStart();
}
protected void onStop() {
super.onStop();
presenter.onStop();
}
public void updateLocationOnMap(Location location) {
// update location on map
}
}
And this will be our Presenter interface
public interface MainPresenter {
void onStart();
void onStop();
}
And this is our Presenter implementer
public class MainPresenterImplementer implements MainPresenter {
private final LocationRetriever locationRetriever;
MainPresenterImplementer(MainView view) {
locationRetriever = new LocationRetriever() {
public void onLocationChanged(Location location) {
view.updateLocationOnMap(location);
}
};
}
public void onStart() {
locationRetriever.start();
}
public void onStop() {
locationRetriever.stop();
}
}
Now we have to tell the Presenter what is our Life-Cycle state so it can handle starting and stopping the Location-Retriever
The Easy Way
Instead of adding the Life-Cycle related methods in the Presenter interface, and handling invoking them manually in our Activity (or Fragment), we can use Lite-Cycle library to handle this for us, just do the following
Step 1 - update Gradle dependencies :
dependencies {
...
implementation 'com.android.support:appcompat-v7:26.1.0' // must be 26+
implementation 'com.github.Ahmed-Adel-Ismail:LiteCycle:1.1.1'
}
Step 2 - update the View interface to extend the Life-Cycle Owner interface
public interface MainView extends LifecycleOwner {
void updateLocationOnMap(Location location);
}
Step 3 - remove Life-Cycle related methods from Presenter interface
public interface MainPresenter {
}
Step 4 - update the Presenter Implementer with Lite-Cycle
public class MainPresenterImplementer implements MainPresenter {
MainPresenterImplementer(MainView view) {
LiteCycle.with(locationRetriever(view))
.forLifeCycle(view)
.onStartInvoke(locationRetriever -> locationRetriever.start())
.onStopInvoke(locationRetriever -> locationRetriever.stop())
.observe();
}
private LocationRetriever locationRetriever(final MainView view) {
return new LocationRetriever() {
public void onLocationChanged(Location location) {
view.updateLocationOnMap(location);
}
};
}
}
Now in the Presenter, the Lite-Cycle will handle invoking LocationRetriever.start() in the onStart() method, and will invoke LocationRetriever.stop() in the onStop() method ... now we only need to initialize our LocationRetriever, and this is done in the method locationRetriever(MainView)
Step 5 - update the Activity
public class MainActivity extends AppCompatActivity implements MainView{
private MainPresenter presenter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
presenter = new MainPresenterImplementer(this);
}
@Override
public void updateLocationOnMap(Location location) {
// update location on map
}
}
Conclusion
As you can see, we nearly eliminated the boilerplate code, so instead of declaring methods related to Life-Cycle in our Presenter interface, and using them in our Activity or Fragment, and implementing them in our Presenter Implementer ... now all this is gone, so we have a Life-Cycle free Presenter, and a Life-Cycle free Activity ... all is handled by the Lite-Cycle library ... for more info about the Lite-Cycle library, take a look at this link :
Coding??GreenNotes Into Existence ????
7 年Very nice ??
Software Developer at Improving
7 年I think you mean lightcycle. Edit: actually, never mind. That's yet another lifecycle library.
Mobile Engineer at Rally Health
7 年Clear solution. Thanks for the info. I was doing the same approach creating a BaseActivity and implementing there the lifecycle. And every presenter can handle the lifecycle if they want to.
Flutter | Android | Kotlin & Java developer
7 年why we use library if we can do this without any large effort
Staff iOS Engineer | Building Scalable Mobile Apps | Mobile Lead | Mentor
7 年Great work, we waiting for more :) We need an article clear the clean arch package organizations .. what right to do, and what's wrong,, who is the responsible for dissection of source of data the use cases or the repository