Android框架设计之MVP

概述

  • 定义
    MVP 其实是 MVC 的一种演进版本,它更简单,将 MVC 中的 Controller 改为了 Presenter,View 通过接口与 Presenter 进行交互,降低耦合,方便进行单元测试。

    View:负责绘制 UI 元素、与用户进行交互(Activity、View、Fragment 都可以做为 View 层);
    Model:对数据的操作、对网络等的操作,和业务相关的逻辑处理;
    Presenter:作为 View 与 Model 交互的中间纽带,处理与用户交互的逻辑。可以把 Presenter理解为一个中间层的角色,它接受 Model 层的数据,并且处理之后传递给 View 层,还需要处理 View 层的用户交互等操作。

  • 作用
    1、将Model与View彻底分离。
    2、解决MVC中Activity职责过多,代码臃肿的问题

  • 三者关系

    image.png

MVP案例

此实例基于MVC的实例,改造为MVP模式。与MVC不同的是,一般Activty会当作View层来处理

  • Model层
    跟MVC不同的地方在于Model不会跟View发生交互,只会跟Presenter交互,实现了View和Model的完全分离。
data class UserModel(var userName:String){

    fun login(result: Int, listener: ModelCallBack){
        if (result == 1){
            listener.onSuccess("${userName}登录成功")
        }else{
            listener.onFailed("${userName}登录失败")
        }
    }

    //回调接口 根据是否成功返回数据
    interface ModelCallBack{
        fun onSuccess(msg:String)
        fun onFailed(msg:String)
    }
}
  • View层
    在MVP中Activity充当View层角色,并持有Presenter对象的引用。
    创建IView接口,由Activity(即View层)实现方法,并暴露给Presenter调用,用于更新View。
interface IView {
    fun updateUI(msg:String)
}

Activity类:

class MainActivity : AppCompatActivity(),IView{
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val userPresenter = UserPresenter(this)
        //点击事件  模拟向服务器请求登录
        loginBtn.setOnClickListener{
            userPresenter.login()
        }
    }
    
    //实现更新界面的方法 暴露给Present调用
    override fun updateUI(msg:String) {
        textView.text = msg
    }
}
  • Presenter层
    Present作为中间层,负责业务逻辑处理。
    创建IPresenter接口,由Present层实现,暴露给View层调用
interface IPresenter{
    fun login()
}

Presenter类

class UserPresenter : UserModel.ModelCallBack,IPresenter{
    lateinit var userModel:UserModel
    lateinit var iView:IView
    constructor(iView: IView){
        this.iView = iView
        userModel = UserModel("用户${(0..9).random()}")
    }
    override fun onSuccess(msg: String) {
        iView.updateUI(msg)
    }

    override fun onFailed(msg: String) {
        iView.updateUI(msg)
    }

    override fun login() {
        userModel.login((0..1).random(),this)
    }
}

运行结果

MVP关键点

  • View 不再负责同步的逻辑,而是由 Presenter 负责。Presenter 中既有业务逻辑也有同步逻辑。

  • View 需要提供操作界面的接口给 Presenter 进行调用。(关键)

  • 与MVC的不同

    对比在 MVC 中,Controller 是不能操作 View 的,View 也没有提供相应的接口;而在 MVP
    当中,Presenter 可以操作 View,View 需要提供一组对界面操作的接口给 Presenter 进行调
    用;Model 仍然通过事件广播自己的变更,但由 Presenter 监听而不是 View。

MVP的优缺点

  • 优点

  • 便于测试。Presenter 对 View 是通过接口进行,在对 Presenter 进行不依赖 UI 环境的单元测试的时候。可以通过 Mock 一个 View 对象,这个对象只需要实现了View 的接口即可。然后依赖注入到 Presenter中,单元测试的时候就可以完整的测试 Presenter 业务逻辑的正确性。

  • View 可以进行组件化。在 MVP 当中,View 不依赖 Model。这样就可以让 View 从特定的业务场景中脱离出来,可以说 View 可以做到对业务逻辑完全无知。它只需要提供一系列接口提供给上层操作。这样就可以做高度可复用的 View 组件。

  • 缺点

  • 维护成本相对较高。Presenter 中除了业务逻辑以外,还有大量的 View->Model,Model->View 的手动同步逻辑,造成Presenter 比较笨重,维护起来会比较困难。

  • 系统内存不足时,系统会回收Activity。一般我们都是用OnSaveInstanceState()去保存状态,用OnRestoreInstanceState()去恢复状态。但是在我们的MVP中,View层是不应该去直接操作Model的,所以这样做不合理,同时也增大了M与V的耦合。解决办法是不要将Activity作为View层,可以把Activity当Presenter来处理。具体实现这里就不分析了,有兴趣的可以研究一下。

  • UI改变的话,比如TextView 替换 EditText,可能导致Presente的一些更新UI的接口也跟着需要更改,存在一定的耦合。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352