聊聊 MVP 的缺点

作者: Android架构师丨小熊 | 来源:发表于2019-08-23 10:05 被阅读1次

    设计 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 中。

    最后

    漫漫开发之路,我们只是其中的一小部分……只有不断的学习、进阶,才是我们的出路!才跟得上时代的进步!

    今年年初我花一个月的时间收录整理了一套知识体系,如果有想法深入的系统化的去学习的,资料免费领取方式:加群:797404811,我会把我收录整理的资料都送给大家,帮助大家更快的进阶。

    重要的事说三遍,转发+转发+转发,让更多需要的朋友们都可以看到并且领到!

    相关文章

      网友评论

        本文标题:聊聊 MVP 的缺点

        本文链接:https://www.haomeiwen.com/subject/sohzsctx.html