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. Built with VitePress