How to Code MVP in Android
- This is a simplified MVP structure. In reality, you can inject more lifecycle handling.
- This example is just for illustrating the MVP pattern. In modern Android development, MVP is rarely used, so we won’t go into more advanced details here.
- If you combine it with AutoService, MVP can become slightly more convenient — but generally, you might as well use MVVM directly.
MVP with Kotlin
kotlin
interface IContract {
interface IViewRender {
fun callback(message: String)
}
interface IPresenter {
fun fetchData()
fun onDestroy()
}
}
class View : IContract.IViewRender {
private val presenter: Presenter = Presenter(this)
override fun onViewCreated() {
presenter.fetchData()
}
override fun onDestroy() {
// Cancel any network requests in Presenter
presenter.onDestroy()
}
override fun callback(message: String) {
mBinding.tvInfo.text = message
}
}
// Presenter
class Presenter(
val viewRender: IContract.IViewRender,
) : IContract.IPresenter {
private val mCompositeDisposable = CompositeDisposable()
override fun fetchData() {
Single.create<String> { emitter ->
Thread.sleep(2000L) // Simulate a time-consuming operation
emitter.onSuccess("Hello World")
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object: SingleObserver<String> {
override fun onSubscribe(disposable: Disposable) {
mCompositeDisposable.add(disposable)
}
override fun onSuccess(result: String) {
viewRender.callback(result)
}
override fun onError(e: Throwable) = Unit
})
}
override fun onDestroy() {
mCompositeDisposable.clear()
}
}
Explanation: Here, we use the Activity/Fragment lifecycle to cancel network requests during destruction. This prevents callbacks from trying to update UI on a destroyed view, avoiding potential
NullPointerException
.
MVP with Java
1. Define the Contract
java
public interface IContract {
interface IViewRender {
void callback(@NotNull String message);
}
interface IPresenter {
void fetchData();
void onDestroy();
}
}
2. Implement the View Layer
Bind the View to the Presenter and handle lifecycle events:
java
public class BusinessFragment extends Fragment implements IContract.IViewRender {
private final Presenter presenter = new Presenter(this);
@Override
public void onViewCreated() {
presenter.fetchData();
}
@Override
public void onDestroy() {
presenter.onDestroy();
}
@Override
public void callback(@NotNull String message) {
mBinding.tvInfo.setText(message);
}
}
3. Implement the Presenter
java
public class BusinessPresenter implements IContract.IPresenter {
@NotNull
private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
@NotNull
private final IContract.IViewRender viewRender;
public BusinessPresenter(@NotNull IContract.IViewRender viewRender) {
this.viewRender = viewRender;
}
@Override
public void fetchData() {
Single.create((SingleEmitter<String> emitter) -> {
Thread.sleep(2000L); // Simulate a time-consuming operation
emitter.onSuccess("Hello World");
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<String>() {
@Override
public void onSubscribe(Disposable disposable) {
mCompositeDisposable.add(disposable);
}
@Override
public void onSuccess(String result) {
viewRender.callback(result);
}
@Override
public void onError(Throwable e) {
// ignored
}
});
}
@Override
public void onDestroy() {
mCompositeDisposable.clear();
}
}
Key Point: The Presenter uses
CompositeDisposable
to manage network requests and avoid memory leaks. Lifecycle awareness ensures callbacks are not sent to destroyed views.