MVP简介
本文使用kotlin代码来写的,在项目中 View 和 Model 并不直接交互,而是使用 Presenter 作为 View 和 Model 之间的桥梁。其中 Presenter 中同时持有 View 层以及 Model 层的 Interface 的引用,而 View 层持有 Presenter 层 Interface 的引用,当 View 层某个页面需要展示某些数据的时候,首先会调用Presenter 层的某个接口,然后 Presenter 层会调用 Model 层请求数据,当 Model 层数据加载成功之后会调用 Presenter 层的回调方法通知 Presenter 层数据加载完毕,最后 Presenter 层再调用 View 层的接口将加载后的数据展示给用户。这就是 MVP 模式的核心过程。
这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。
1、常规的MVP介绍
各个分层的作用
- Model:负责提供数据(包括从服务端获取,本地获取的数据);
- View:框架中的视图模块,负责UI展示,UI变更;
- Presenter:程序中的逻辑模块,负责处理具体事务,逻辑;
Base基类
- BaseView:用于创建基类View,统一管理view;
- BasePresenter:所有Presenter层的抽象类,负责Model、View层的引用和销毁;
我们来看看项目结构:
接下来看看各个类的代码
MainContract
/**
* 契约接口,可以很直观的看到 M、V、P 层接口中提供的方法
*/
interface MainContract {
interface IMainModel {
fun getDataFromModel(callback: (String?) -> Unit)
}
interface IMainView {
fun showDialog()
fun updataUI(content: String?)
}
interface IMainPresenter {
fun handlerData()
}
}
MainActivity
/**
* MVP 的写法,Version 1: 基础写法
*/
class MainActivity : AppCompatActivity(),
MainContract.IMainView {
private var mPresenter: MainPresenter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mPresenter = MainPresenter(this)
mPresenter!!.handlerData()
}
override fun showDialog() {
val dialog = ProgressDialog(this)
dialog.show()
Handler().postDelayed({ dialog.dismiss() }, 1500)
}
override fun updataUI(content: String?) {
runOnUiThread {
Toast.makeText(this@MainActivity, "" + content, Toast.LENGTH_SHORT).show()
tv!!.text = content
}
}
}
MainPresenter
/**
* presenter 层,承担业务逻辑处理,数据源处理等
*/
class MainPresenter(private val mView: MainContract.IMainView?) : MainContract.IMainPresenter {
private val mModel: MainContract.IMainModel
init {
mModel = DataModel()
}
override fun handlerData() {
mView?.showDialog()
//发起请求,获得回调数据
mModel.getDataFromModel {
//经过对数据处理,非空处理,逻辑判断等等,最后更新UI
mView?.updataUI(it)
}
}
}
DataModel
/**
* model 层,请求网络或数据库,提供数据源(原始数据)
*/
class DataModel : MainContract.IMainModel {
override fun getDataFromModel(callback: (String?) -> Unit) {
//此处经过网络请求,获取到数据之后,返回去
callback("返回数据:123456")
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".v1.view.MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2、封装成baseMvp的模式
关于封装baseMvp,过程有点多,这里就不做详细的介绍,下面来看看项目结构图
加入一个我自己封装的volley网络请求工具类volleyUtil,用作请求响应的展示。
需要retrofit的同学,可以到我的另外一篇博客里看
最后全部的代码都在这里:https://download.csdn.net/download/wy313622821/12812143