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()
// To Bind the lifecycle Access Process Interface
fun attachView(viewRender: IContract.IViewRender)
fun detachView()
}
}
class View : IContract.IViewRender {
private val presenter: Presenter = Presenter()
override fun onViewCreated() {
presenter.attachView(this)
presenter.fetchData()
}
override fun onDestroy() {
// Cancel any network requests in Presenter
presenter.detachView()
}
override fun callback(message: String) {
mBinding.tvInfo.text = message
}
}
// Presenter
class Presenter : IContract.IPresenter {
private var viewRender: IContract.IViewRender? = null
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 attachView(viewRender: IContract.IViewRender) {
this.viewRender = viewRender
}
override fun detachView() {
mCompositeDisposable.clear()
viewRender = null
}
}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.