Skip to content

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.

Just something casual. Hope you like it.