1. What is that?
MVP是一种设计模式(框架),因为其出色的解耦功能广泛地用于Android工程中,它将应用程序分为Model-View-Presenter,各司其职,简称MVP
- Model(模型) 负责对数据的处理和存储,将数据回调给Presenter
- Presenter(主持者) 负责将View层的请求(如点击,更新视图数据)进行转发给对应的Model,接受回调后再通知View层更新视图
- View(视图) 仅负责将显示数据
- Contract(契约类) 仅仅用于定义View和Model的接口,便于管理和查看
一次简单的更新视图的基本流程
顺序就是按照①②③④⑤来进行
1️⃣在View中,我们向Presenter发送一次更新TextView的请求
2️⃣Presenter收到请求后再向对应的Model发送获取String的请求(中间可能有耗时操作,所以可能需要回调接口)
3️⃣成功拿到数据后再通过回调接口给Presenter
4️⃣Presenter拿到数据后再触发View的回调
5️⃣最后完成View的视图更新。
自始至终,View做的事情只有处理用户的请求(更新TextView)并发送给Presenter,然后提供一个用来更新视图的回调;Presenter做的事情只有转发,自己本身不处理逻辑;model负责提供信息,同时包括数据的处理。
有的版本的MVP可能选择将数据处理放入Presenter中,然后model只有一个setter/getter的类似JavaBean的作用,但是我觉得这样处理使得Presenter变得很臃肿,所以我选择将逻辑处理放入Model。两种方式都可以√
2. MVP通用框架
2.1 Contract层
Contract并没有什么很通用个框架,因为每个视图和每一个model的工作各不相同,这里给出的是上图中的的范例
class DetailContract{
interface DetailView{
fun onChangeText(String)
}
interface DetailModel {
fun getNowText(callBack: GetTextCallBack)
}
interface GetTextCallBack{
fun onSuccess(str:String)
fun onFail(info:String)
}
}
2.2 Model层
Model也没有什么很通用的框架,这里给出的是上图中的范例
class SampleModel: DetailContract.DetailModel{
override getNowText(callBack: GetTextCallBack){
val str = ...
//以上是获取String的操作
if(str!=""){
callBack.onSuccess(str)
}else{
callBake.onFail("获取失败")
}
}
}
这里的具体Model类实现了Contract契约类中的接口,方便我们Presenter进行调用
2.3 View层
View在Android中一般包括两种,一种是Activity,一种是Fragment,这里只给出Activity的封装,Fragment类似,需要处理一些生命周期的问题。
Activity:
abstract class BaseActivity<V,T:BasePresenter<V>>:Activity(){
val TAG:String = javaClass.simpleName
protected lateinit var mPresenter: T
lateinit var mContext: Context
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mContext = this
//初始化Presenter
mPresenter = createPresenter()
//将Presenter和View绑定
mPresenter.attachView(this as V)
//初始化布局
initView(savedInstanceState)
}
/**
* 应该由子类进行实现的初始化view的方法
*/
abstract fun initView(savedInstanceState: Bundle?)
/**
* 创建对应的Presenter
*/
abstract fun createPresenter():T
//解除绑定
override fun onDestroy() {
super.onDestroy()
mPresenter.detachView()
}
}
BaseActivity是一个抽象类,所有加入MVP模式的Activity都应该继承这个抽象类。 泛型V代表的是视图(即自己),T则是对应的Presenter。View层持有对应Presenter的引用,用来发送消息。
2.4 Presenter层
abstract class BasePresenter<T> {
//View接口类型的弱引用,防止所持有的view已经被销毁,但是该presenter仍然持有,导致内存的泄露
protected lateinit var mViewRef:Reference<T>
//绑定View引用
fun attachView(view:T){
mViewRef = SoftReference<T>(view)
}
//获取当前绑定的View引用
protected fun getView(): T? {
return mViewRef.get()
}
//是否已绑定View
fun isViewAttached(): Boolean {
return mViewRef != null&&mViewRef.get()!=null
}
//解除引用
fun detachView(){
if (mViewRef != null){
mViewRef.clear()
}
}
}
BasePresenter是一个抽象类,所有加入MVP模式的Presenter都应该继承该抽象类。
Presenter持有View层的一个弱引用,同时包括4个和弱引用有关的方法,分别是绑定View的引用,获取当前View的引用,判定是否已绑定了View,解除View的引用。
在具体的Presenter中还拥有一个对应Model对象。也就是Presenter同时持有View和Model,这样才可以做到信息的转发功能
传入的是Contract中的View接口类型是因为可以使得Presenter只通过接口向view传输传输信息。而不是一个具体的类型。
扫描二维码关注公众号,回复: 6301750 查看本文章
以上就是一些常用的框架,下面我们用实战来继续加深理解:
3. 实战
该范例选自红岩移动开发部的中期考核,内容为一个音乐App。仅仅分析播放页面(因为我就做了两个页面