面试问到烂的MVC、MVP以及MVVM

浩浩 等级 805 1 1

MVP

什么是MVP?

在了解MVP之前可以先观察MVC的架构模式。

面试问到烂的MVC、MVP以及MVVM

MVC中三个组成部分:1. View,即视图中的各个控件;2. Controller,即Activity、Fragment;3. Model,即数据源。

但是日常开发中能够发现,对View层的控制也是在Activity中,这时引入Model层数据源的获取再与Controller层发生交互时,不难发现MVC三层互相都存在持有关系,也就产生了严重的耦合。

面试问到烂的MVC、MVP以及MVVM

图片

而MVP的架构实现就是将控制层下移,View层充当Activity、Fragment的存在,Model层保持原样作为数据源的获取层存在,而View和Model层的通信通过中间人Presenter来完成数据的传递,通过这样的方式达到了解耦的目的。

通信的方式就是互相持有,但中间人对于View层的持有使用弱引用的方式实现,以保证View的及时释放。

内存泄漏

解耦的思想在上面已经有所表述,但解耦的背后还有一个我们非常关注的点 --内存泄漏。这个小模块可以分为两个问题进行阐述:1. 什么是内存泄漏?;2. 使用MVP框架能不能帮我们解决内存泄漏的问题?

什么是内存泄漏?

想来这也是老生常谈的问题了,简单了说原本该释放的东西最后竟然没有释放掉,而引起问题可能是一个变量、一个任务等等。

使用MVP框架能不能帮我们解决内存泄漏的问题?

其实这个问题我们应该这样去进行发问MVP框架能不能帮我们解决View层内存泄漏的问题?如果使用标题的问题,其实这算是一个错误的命题,

那是否能够解决这样的问题呢?可以通过一个非常简单的方法直接进行验证。下面是一段代码示例,一个简单的异步线程延迟任务。

new Thread(new Runnable() {
    @Override
    public void run() {
        SystemClock.sleep(200000);
    }
}).start(); 

通过Android Studio集成的Profiler能力,在运行期间就可以直接分析内存信息。

面试问到烂的MVC、MVP以及MVVM

图片

面试问到烂的MVC、MVP以及MVVM

图片

其中有一个打了红框的按钮,点击后可以打印出一段时间的内存分配情况。 你同样可以直接点击对某个时间点进行分析。

这是有两个信息我们去进行关注,View层、Prensenter层、Model层所占用的内存大小。

  1. View层

面试问到烂的MVC、MVP以及MVVM

图片

  1. Presenter层和Model层

面试问到烂的MVC、MVP以及MVVM

图片

上述的Presenter层中已经开启了异步线程,能够明显发现View层所占用的内存明显大于Presenter层和Model层。而如果这个时候使得让我去选择内存泄漏的类,最后的选择肯定是倾向是少的一方,而MVP给我们带来了选择的空间,这也是MVP架构下为我们带来的一大好处。

这里也得出了一个标题的结论,MVP架构能够缓解内存泄漏问题,但不能解决它。

手撸一个MVP架构

在MVP架构中,我们会存在两种代码风格,M层或P层做复杂的逻辑处理,选择其中一层做复杂的逻辑处理,在这里我更喜欢这些事情由M层负责完成。

M-V-P

首先是Presenter层,这一层作为中间人,和Model层以及View层同时存在通信,也就需要对两者同时进行持有,另外为了能够在View层销毁不用时,Presenter层能够不发生内存泄漏问题,对于View层引用方法采用的是弱引用的方式书写。

abstract class BaseMvpPresenter<V: IMvpView, M: IMvpModel> : IMvpPresenter {
    private var vWeakReference: WeakReference<V>? = null
    protected val model: M by lazy { createModel() } 
    override fun bindView(mvpView: IMvpView) {
        vWeakReference = WeakReference(mvpView as V)
    }
    override fun unBindView() {
        if (vWeakReference != null) {
            vWeakReference?.clear()
            vWeakReference = null
        }
    }
    fun getView(): V? = vWeakReference?.get()
    abstract fun createModel(): M
} 

接下来是Model层,这一层是数据源的存在,而数据源的获取方法都是用户自定义,这里Model层只需要在持有Presenter层的前提下做能力预留即可。

abstract class BaseMvpModel<P: IMvpPresenter> (val p: P): IMvpModel 

最后是View层,更具体一点就是Activity、Fragment这些类,一个同样避不开的话题就是持有,View层同样需要先对Presenter层进行持有,也就有了如下的初版代码。

abstract class BaseMvpActivity<P : BaseMvpPresenter<*, *>> : AppCompatActivity(), IMvpView {
    protected var p: P? = null

    abstract fun getPresenter(): P
} 

但是需要思考的一个问题Activity、Fragment什么时候应该和Presenter层发生通信呢?为了能够适应全生命周期的变化,自然最后的考虑就是Activity的onCreate()和onDestroy(),Fragment的onAttach()和onDetach()方法中了。

abstract class BaseMvpActivity<P : BaseMvpPresenter<*, *>> : AppCompatActivity(), IMvpView {
    protected var p: P? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        p = getPresenter()
        p?.bindView(this)
    }
    override fun onDestroy() {
        super.onDestroy()
        p?.unBindView()
    }
    abstract fun getPresenter(): P
} 

abstract class BaseMvpFragment<P : BaseMvpPresenter<*, *>> : Fragment(), IMvpView {
    protected var p: P? = null
    override fun onAttach(context: Context) {
        super.onAttach(context)
        p = getPresenter()
        p?.bindView(this)
    }
    override fun onDetach() {
        super.onDetach()
        p?.unBindView()
    }
    abstract fun getPresenter(): P
} 

完成以上的一系列步骤,其实已经完成了整个架构的构建,但是如果直接继承去玩这套框架的时候是不是感觉还欠缺了什么东西?通信

建立通信

在刚刚全部代码基础上,不论Model层、Presenter层还是View层都已经做好了最基础的事情,就是持有。但是通信一定需要持有,持有不一定能够通信。显然在现有的代码基础上,通信设施是当务之急。

这也就引出了新的通信层Contract,当然它的本名应该说是协议层,就像TCP / UDP啥的,在不同的层次之间引出了这样一个接口类,他负责的事情就是MVP三层的通信是什么样的。以下便是一段协议层的示例:

interface MainContract {
    interface Model {
        fun execute()
    }
    interface View<T: IMvpModel> {
        fun handleResponse(data: T)
    }
    interface Presenter<T: IMvpModel> {
        fun request()
        fun response(data: T)
    }
} 

通过在不同的层次引入这些接口,并完成其具体实现,最后就实现了一套完整的MVP架构。

MVVM

面试问到烂的MVC、MVP以及MVVM

MVVM架构其实和MVP架构整体上相似,但是ViewModel层和View层属于双向通信,使用了DataBinding的能力,使得ViewModel的生成、与View层的绑定完全由系统直接完成简化了开发的流程。但是从设计上出发的时候,MVP更有利于我们对于整体架构的理解。

入门MVVM

  1. 能力引入

android {
  dataBinding {
        enabled true
    }
} 

使用Kotlin编程的开发者需要引入kotlin-kapt

  1. 使用

使用方面可以分为两个小部分:布局使用、绑定使用

  • 布局使用

在布局使用中和平常的XML编写会有一定的出入,需要使用进行第一层的包裹,而其中的代码编写又可以分为数据区布局区两个部分。布局区和平常的书写方式保持一致,重点关注数据区,他需要以做第一层包裹,用于标示数据区,是对变量的定义,其中标签是定义该变量变量名,标签是定义该变量的类型。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="user"
            type="com.clericyi.android.helper.LoginModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.responseCode}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout> 
  • 绑定使用

完成布局绑定以后需要Sync,这一套能力实现和ButterKnife一样都会产生一个新的Binding文件,但是这个Binding拥有更为强大的数据绑定能力。另外这个Binding文件的命名是和XML文件保持一致的,比如activity_main.xml => ActivityMainBinding,activity_main_1.xml => ActivityMain1Binding。

val ac = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
ac.user = p?.let { LoginModel(it, "200") } 

以上一套非常简单的代码过后就已经完成了这套生态下的大部分事项,从开发成本上来讲是优于MVP架构的。

学习最忌盲目,无计划,零碎的知识点无法串成系统。学到哪,忘到哪,面试想不起来。这里我整理了Android面试中最常问的核心知识点以及Android架构、Flutter、KT、framework中最核心的几块知识,分享在我的【Github】,如有面试需要的朋友欢迎前往阅读;

收藏
评论区

相关推荐

面试问到烂的MVC、MVP以及MVVM
MVP 什么是MVP? 在了解MVP之前可以先观察MVC的架构模式。 MVC中三个组成部分:1. View,即视图中的各个控件;2. Controller
Vue进阶(四十七):面试必备:2021 Vue经典面试题总结(含答案)_IT全栈 华强工作室
面试必备:2021 Vue经典面试题总结(含答案)一、什么是MVVM?
最新最全的 Vue 面试题 ➕详解答案
前言本文整理了高频出现的 Vue 相关面试题并且附带详解答案 难度分为简单 中等 困难 三种类型 大家可以先不看答案自测一下自己的 Vue 水平哈 整理不易 如果觉得本文有帮助 记得点赞三连哦 十分感谢! 简单 1 MVC 和 MVVM 区别 MVCMVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器
移动开发技术总结!看我如何一步一步攻克面试官
Android开发者该如何提升自己?我有两点建议: 1、横向发展:(适合有自己专精技术的人) 在自己擅长领域深入钻研的同时,会Hybrid开发(Flutter,RN,H5)之外,还要会web开发、微信小程序。但是,这确实比较难,全栈容易发展成全菜,啥都知道,啥都不精。 2、纵向发展:(适合大多数人) 如果做应用开发,就往应用架构方向发展;如果做系统层开发,就
这是一份用心整理的Android面试总结,涨姿势!
Android Jetpack组件的作用是什么? Navigation:一个用于管理Fragment切换的工具类,可视化、可绑定控件、支持动画等是其优点。 Data Binding:不用说,都知道,加速MVVM的创建。 Lifecycle:他是我们能够处理Activity和Fragment的生命周期的重要原因,在AndroidX的Fragment和Activ
11个显著提升 ASP.NET 应用程序性能的技巧——第1部分
**【编者按】本文出自站外作者 Brij Bhushan Mishra ,Brij 是微软 MVP-ASP.NET/IIS、C# Corner MVP、CodeProject Insider,前 CodeProject MVP,CodeProject Mentor 以及 CodeProject Platinum Member,拥有6年左右的高级开发工程师/架
JS 框架整理
**(1)MVC** ---------- Ember.js、Backbone.js、Knockout.js、Spine.js、Batman.js 、 Angular.js、Canjs、Batman.js [12 款优秀的 JavaScript MVC 框架评估](https://www.oschina.net/action/GoToLink?url=h
Oracle 19c迁移前,做好RAT回放测试有多重要?
作者介绍 **梁铭图,**新炬网络首席架构师,十多年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有Oracle OCM、Togaf企业架构师(鉴定级)、IBM CATE等认证,曾获dbaplus年度MVP以及华为云MVP等荣誉,并参与数据资产管理国家标准的编写工作。在数据库运维管理和架构设计、运维体系规划、数据资产管理方面有深入研究。 **背
Android MVP模式
**1、MVP模式简介** ------------- 相信大家对MVC都是比较熟悉了:M-Model-模型、V-View-视图、C-Controller-控制器,MVP作为MVC的演化版本,那么类似的MVP所对应的意义:M-Model-模型、V-View-视图、P-Presenter-表示器。 从MVC和MVP两者结合来看,Controlller/Pre
CloudReader [云阅]
CloudReader =========== \> Netease cloud music Ui && Retrofit2 + RxJava2 + MVVM-databinding && wanandroid、Gank.Io、mtime Api GitHub地址:[https://github.com/youlookwhat/CloudReader](
JetPack之ViewModel最新源码详细分析
本文会基于最新版ViewModel使用方法与源码进行详细分析,从注册到实现ViewModel界面数据如何保存与管理全部涉及。 \*\* 简介: --- \*\*`ViewModel`是JetPack系列库之一,它用来对组件的界面数据进行管理,且当组件的状态发生改变时数据依然留存。 优点:1.当所依赖组件的状态发生改变时,例如屏幕旋转等,界面数据不会发
MVVM和MVC的区别,以及MVVM的缺点
**MVVM和MVC的区别** MVC和MVVM的区别其实并不大。都是一种设计思想。 主要就是MVC中Controller演变成MVVM中的viewModel。 MVVM主要解决了MVC中大量的DOM操作使页面渲染性能降低,加载速度变慢,影响用户体验。 当和Model频繁发生变化,开发者需要主动更新到View。 **MVVM:是Model-View
Node.js 开发实践,前端工程师的 MVP 利器
![](https://oscimg.oschina.net/oscnet/c2250098-bead-4599-a9de-8b97c4c61c63.png) > 本文经作者授权转载至公众号 “Nodejs技术栈”,作者:愚坤,掘金优秀作者,一名没上高中的前端工程师,目前就职水滴筹。 什么是 MVP,来自伟大的百科: > **Minimum Viabl
Vue 入门
Vue.js 是构建用户界面的MVVM框架 ,只关注视图层 Vue将DOM和数据绑定起来,一旦创建了绑定,DOM将和数据保持同步,每当变更了数据,DOM也会相应地更新。这样就减少了不必要的DOM操作提高渲染效率,让前端程序员只需要关心业务逻辑不再关心DOM是如何渲染的 **MVC**和**MVVM**的区别:MVC是后端分层开发概念,MVVM是前端视图层
阿里巴巴前端练习生学习笔记
字符串引擎和Javascript引擎的区别:是否对于DOM进行全部改变? 相关资料链接• Wiki MVC • Wiki MVVM • Mustach • Handlebars • React • Angular • Vue • Bootstrap • Ant Design • Fusion Des