聊聊 MVP 的缺点

简介: 聊聊 MVP 的缺点

设计 MVP 的目的:


  • 解锁 V 层的臃肿

极差体验:


1、继承

继承方式真的太糟糕了,BaseMVPActivity 本身是一种下沉到 lib 的通用类,但上层的业务层需要采用 BaseActivity 的方式来实现基础统计和埋点,意味着,我要么把 BaseMVPActivity 提到业务层,然后继承 BaseActivity,或是把 BaseActivity 下沉到 lib,供 BaseMVPActivity 继承,但我的业务统计就没办法用了。


public abstract class BaseMVPActivity<P extends MVPBasePresenter> extends BaseActivity implements MVPBaseView
复制代码

2、赋予 P 层生命周期感知


private P presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (presenter == null) {
            presenter = createPresenter();
        }
        presenter.attach((V) this);
    }
    @Override
    protected void onDestroy() {
        presenter.detach();
        super.onDestroy();
    }
复制代码


这种方式优缺点都有:


优点是:V 层在结束页面时,无需关心数据的释放动作

缺点是:P 层在 detach 时操作了 M 层的耗时任务,会直接导致 V 层 ANR

我觉得,P 层不应该具有生命周期的感知能力


3、糟糕的接口约束


V 层调用 P 层会制定一层接口来约束当前可调用的方法,P 层在完成任务动作时,也会通过约束接口将数据回调回给 V 层,接口制定如下:


public interface HandleContract {
    interface View extends BaseView {
        void startWayPointSuccess();
        void pauseWayPointSuccess();
        void resumeWayPointSuccess();
        void clearWayPointSuccess();
        void stopWayPointSuccess();
    }
    interface Present extends BasePresenter {
        void startWayPointMission();
        void pauseWayPointMission();
        void resumeWayPointMission();
        void clearWayPointMission();
        void stopWayPointMission();
    }
}
复制代码


之前一直认为,通过接口约束来实现 V 与 P 的调用模板,可以很清晰的明白双方的执行动作,但,在业务的持续变化中,由于某些接口约束已不再有用,我就需要不停的去修改这个接口模板,修改了模板之后,我还要去修改 V 层实现的方法,P 层实现的方法,并且,当业务量上来之后,整个接口调用层非常乱,为了跟踪一个功能,V 层跳 P ,P 层跳 V,跳了好几层,终于明白了这个功能实现了什么动作。

想法



我一直认为 ViewModel+LiveData+Lifecycles 是一个非常好的解决的方案,ViewModel 在 Framework 层面已经做了 ViewModelStore 的支持,Lifecycles 也在 ComponentActivity 中注册了 LifecycleRegistry,LiveData 在 observe(this,observer) 时持有了 LifecycleOwner,拥有了生命周期的感知能力。

1、第一点: 数据交互


View 层只需要初始化 ViewModel,订阅 ViewModel 中的 LiveData,以观察者的身份观察数据,一旦有数据的变化,就会自动更新到 View 中,而不需要像 V 与 P 的关系,在获取数据时,先触发 P,拿到数据后,P 层再调用 V 来更新数据,相比 ViewModel 的方式,多了一层手动设置数据返回,而为了数据返回,又多了一层接口模板来规范约束,最终,整个代码就是一个饼。

2、第二点:生命周期感知


LiveData 拥有的生命周期感知能力与 Present 还是有点区别的, 具体区别是在实现层面上:

1、LiveData 的生命周期感知是在 observe 时,将自己 addObserver 到 Lifecycle 中,让 Fragmentwork 层来赋予自己生命周期的感知能力

2、Present 生命周期感知是  BaseMVPActivity 赋予 BaseMVPPresent 的,如果我们的 Present 具有感知能力,就需要继承 BaseMVPPresent,这一点我在上面的继承中就表明了,这个是极差体验点,我们可以看下 ViewModel+LiveData 的方式,所有的操作都是在组合,组合的好处是什么呢?当然是为了在业务升级时有利于拆解和组装,而继承,不具有这样的特性

3、第三点:页面重建


屏幕旋转时页面发生重建,我们需要在在页面销毁时保存数据,重建时恢复,但数据的存储是有容量限制的,并且对象存储必须是序列化对象,苛刻的条件,Present 是无法做到的,然而,ViewModel 却是可以的,ViewModel 并不是通过 Bundle 的方式来实现数据的存储,而是通过 Framework 的支持,存储在 ViewModelStore 中,具体剖析可以查看文章 《ViewModel 凭什么能保存重建数据

目录
相关文章
|
4月前
|
存储 测试技术 数据库
谈谈代码:降低复杂度,从放弃三层架构到DDD入门
最近我发现团队某项目的复杂度越来越高(典型的三层架构),具体表现为: - 代码可读性较差:各个服务之间调用复杂,流程不清晰 - 修改某服务业务代码导致大量无关服务的测试用例失败,单个功能开发者很难迅速定位相关问题 - 测试用例特别难编写,需要mock大量数据来拉起整块服务
102 4
谈谈代码:降低复杂度,从放弃三层架构到DDD入门
|
8月前
|
机器学习/深度学习 SQL 人工智能
应用开发者的疑问:大模型是真正的银弹吗?
通过本文作者想和大家简单讨论下大模型的局限以及真正的适用场景。
83906 30
应用开发者的疑问:大模型是真正的银弹吗?
|
9月前
|
机器学习/深度学习 SQL 人工智能
应用开发者的疑问:大模型是银弹吗?
ChatGPT 火了之后,大模型似乎被当成了真正的银弹,所有的体验问题都试图通过大模型解决。本文想和大家简单讨论下大模型的局限以及真正的适用场景。由于本人不是专业搞算法的,大佬们多多拍砖。
736 0
|
10月前
|
存储 SQL 前端开发
借一个项目谈Android应用软件架构,你还在套用MVP 或MVVM吗
借一个项目谈Android应用软件架构,你还在套用MVP 或MVVM吗
|
11月前
|
存储 缓存 前端开发
“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(一)
“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(一)
73 0
|
11月前
|
存储 前端开发 网络协议
“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(二)
“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(二)
86 0
|
11月前
|
存储 缓存 前端开发
“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(二)(下)
“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(二)
78 0
|
11月前
|
安全 前端开发 网络协议
MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(三)
MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(三)
100 0
|
11月前
|
设计模式 网络协议 前端开发
MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(一)
MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(一)
64 0
|
11月前
|
存储 缓存 前端开发
MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(二)
MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(二)
81 0