Android 技术架构

1.Android技术架构有哪几种

  • MVC
    • MVC全名是Model View Controller,如图,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
  • MVP
    • MVP从更早的MVC框架演变过来,与MVC有一定的相似性:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
  • MVVM

2.MVC架构简单介绍

2.1 MVC介绍

  • Model View Controller,是软件架构中最常见的一种框架,简单来说就是通过controller的控制去操作model层的数据,并且返回给view层展示,具体见下图
  • image
  • 工作原理
    • 当用户出发事件的时候,view层会发送指令到controller层,接着controller去通知model层更新数据,model层更新完数据以后直接显示在view层上,这就是MVC的工作原理。
      • M层处理数据,业务逻辑等
      • V层处理界面的显示结果
      • C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层

2.2 Android实际应用场景

  • 视图层(View)
    • 一般采用XML文件进行界面的描述,这些XML可以理解为AndroidApp的View。使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中与界面对应的id不变化则代码不用修改,大大增强了代码的可维护性。
  • 控制层(Controller)
    • Android的控制层的重任通常落在了众多的Activity的肩上。这句话也就暗含了不要在Activity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Actiivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
  • 模型层(Model)
    • 针对业务模型,建立的数据结构和相关的类,就可以理解为AndroidApp的Model,Model是与View无关,而与业务相关的。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。
  • 对于Android工程,有Java的class文件,有res文件夹,里面是各种资源,还有类似manifest文件等等。
    对于原生的Android项目来说,
    • layout.xml里面的xml文件就对应于MVC的view层,里面都是一些view的布局代码,
    • 而各种Java bean,还有一些类似repository类就对应于model层,
    • 至于controller层嘛,当然就是各种activity咯。
  • 大家可以试着套用我上面说的MVC的工作原理是理解。比如你的界面有一个按钮,按下这个按钮去网络上下载一个文件,这个按钮是view层的,是使用xml来写的,而那些和网络连接相关的代码写在其他类里,比如你可以写一个专门的networkHelper类,这个就是model层,那怎么连接这两层呢?是通过button.setOnClickListener()这个函数,这个函数就写在了activity中,对应于controller层。是不是很清晰。

2.3 MVC缺陷

  • 问题就在于xml作为view层,控制能力实在太弱了,你想去动态的改变一个页面的背景,或者动态的隐藏/显示一个按钮,这些都没办法在xml中做,只能把代码写在activity中,造成了activity既是controller层,又是view层的这样一个窘境。
  • MVC还有一个重要的缺陷,大家看上面那幅图,view层和model层是相互可知的,这意味着两层之间存在耦合,耦合对于一个大型程序来说是非常致命的,因为这表示开发,测试,维护都需要花大量的精力。
  • Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户 界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。

2.4 MVC最简单的例子

  • 2.4.1 Model层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    //接口
    public interface InterModel {
    void getAboutData(AboutDataListener<OnlineMusicList> listener);
    }

    /**
    * 数据model类
    */
    public class MeAboutModel implements InterModel {
    @Override
    public void getAboutData(final AboutDataListener<OnlineMusicList> listener) {
    //开始请求网络
    OnLineMusicModel model = OnLineMusicModel.getInstance();
    model.getList(OnLineMusicModel.METHOD_LINE_MUSIC , "", 0 ,3)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Consumer<OnlineMusicList>() {
    @Override
    public void accept(OnlineMusicList onlineMusicList) throws Exception {
    listener.onSuccess(onlineMusicList);
    }
    }, new Consumer<Throwable>() {
    @Override
    public void accept(Throwable throwable) throws Exception {
    listener.onError();
    }
    }, new Action() {
    @Override
    public void run() throws Exception {

    }
    });
    }
    }
  • 2.4.2 Controllor(View)层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class MeAboutActivity extends BaseActivity {

    @Override
    public int getContentView() {
    return R.layout.activity_me_about;
    }

    @Override
    public void initView() {

    }

    @Override
    public void initListener() {

    }

    @Override
    public void initData() {
    MeAboutModel mvpModel = new MeAboutModel();
    mvpModel.getAboutData(new AboutDataListener<OnlineMusicList>() {
    @Override
    public void onSuccess(OnlineMusicList onlineMusicList) {

    }

    @Override
    public void onError() {

    }
    });
    }
    }
  • 简单分析下这个例子:

  • 1、activity里面的控件必须关心业务和数据,才能知道自己怎么展示。换句话说,我们很难让两个人在不互相沟通的情况下,一人负责获取数据,一人负责展示UI,然后完成这个功能。

  • 2、所以的逻辑都在activity里面。完美的体现了MVC的两大缺点:View对Model的依赖,会导致View也包含了业务逻辑;Controller会变得很厚很复杂。

3.MVP架构简单介绍

3.1 MVP简单介绍

  • MVP作为MVC的演化,解决了MVC不少的缺点,对于Android来说,MVP的model层相对于MVC是一样的,而activity和fragment不再是controller层,而是纯粹的view层,所有关于用户事件的转发全部交由presenter层处理。
  • image

3.2 MVP工作原理

  • MVP框架由3部分组成:View负责显示,Presenter负责逻辑处理,Model提供数据。在MVP模式里通常包含3个要素(加上View interface是4个):
    • View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity)
    • Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合)
    • Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
      • View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试
  • 从图中就可以看出,最明显的差别就是view层和model层不再相互可知,完全的解耦,取而代之的presenter层充当了桥梁的作用,用于操作view层发出的事件传递到presenter层中,presenter层去操作model层,并且将数据返回给view层,整个过程中view层和model层完全没有联系。看到这里大家可能会问,虽然view层和model层解耦了,但是view层和presenter层不是耦合在一起了吗?其实不是的,对于view层和presenter层的通信,我们是可以通过接口实现的,具体的意思就是说我们的activity,fragment可以去实现实现定义好的接口,而在对应的presenter中通过接口调用方法。不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。这就解决了MVC模式中测试,维护难的问题。
  • 当然,其实最好的方式是使用fragment作为view层,而activity则是用于创建view层(fragment)和presenter层(presenter)的一个控制器。

3.3 MVP最简单的例子

  • 3.3.1 首先来看两个Base接口类

    • BaseView与BasePresenter,两类分别是所有View和Presenter的基类。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public interface BaseView {

    }

    public interface BasePresenter {

    //绑定数据
    void subscribe();
    //解除绑定
    void unSubscribe();

    }
  • 3.3.2 定义了契约类(接口)

    • 也就是contract接口类,主要是activity和presenter中起到桥接作用
    • 使用契约类来统一管理view与presenter的所有的接口,这种方式使得view与presenter中有哪些功能,一目了然,维护起来也很方便。
    • AppContract中的View接口定义了该界面(功能)中所有的UI状态情况,AppActivity作为View层,实现了该接口,如此AppActivity只关注UI相关的状态更新,所有事件操作都调用AppPresenter来完成。
    • Presenter 接口则定义了该界面(功能)中所有的用户操作事件,AppPresenter作为Presenter层,实现了该接口,如此AppPresenter则只关注业务层的逻辑相关,UI的更新只需调用View的状态方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //contract起到桥接的作用
    public interface AppContract {

    interface View extends BaseView {
    void setDataView();
    }

    interface Presenter extends BasePresenter {
    void getData();
    }
    }
  • 3.3.3 Activity在mvp中的作用

    • Activity在项目中是一个全局的控制者,负责创建view以及presenter实例,并将二者联系起来。AppActivity的onCreate()回调中创建并绑定AppPresenter实例,AppPresenter的构造函数中实现了View和Presenter的关联。
    • 然后代码如下所示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    public class AppActivity extends AppCompatActivity implements AppContract.View{

    private AppContract.Presenter mPresenter = new AppPresenter(this);

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_five);
    mPresenter.subscribe();
    mPresenter.getData();
    }

    @Override
    protected void onDestroy() {
    super.onDestroy();
    if(mPresenter!=null){
    mPresenter.unSubscribe();
    }
    }

    @Override
    public void setDataView() {

    }
    }

    //persenter
    public class AppPresenter implements AppContract.Presenter {

    private AppContract.View mView;


    public AppPresenter(AppContract.View androidView) {
    this.mView = androidView;
    }

    @Override
    public void subscribe() {

    }

    @Override
    public void unSubscribe() {

    }

    //从网络获取数据
    @Override
    public void getData() {
    mView.setDataView();
    }
    }

4.MVVM架构简单介绍

4.1 MVVM简单介绍

  • image

4.2 MVVM工作原理

从图中看出,它和MVP的区别貌似不大,只不过是presenter层换成了viewmodel层,还有一点就是view层和viewmodel层是相互绑定的关系,这意味着当你更新viewmodel层的数据的时候,view层会相应的变动ui。

5.三者之间比较

  • MVP模式是从MVC模式演变来的,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示,所以他们之间并没有特别大的不同,都是用来将View和Model之间松耦合。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中是允许Model和View进行交互的。还有重要的一点就是Presenter与View之间的交互是通过接口的。MVVM是通过MVP演变而来的,主要用了data binding来实现双向交互,这就使得视图和控制层之间的耦合程度进一步降低,关注点分离更为彻底,同时减轻了Activity的压力。
  • 关键点总结:
  • MVC
    • Controller是基于行为,并且能够在view之间共享
    • Controller负责接收用户交互等操作,并且决定需要显示的视图。
  • MVP
    • View和Model更加的解耦了,Presenter负责绑定Model到View。
    • 复杂的View可以对应多个Persenter。
    • Presenter保留有View层的事件逻辑,所有的点击之类的事件都直接委托给Presenter。
    • Presenter通过接口直接和View层解耦,所以更加方便的进行View的单元测试。
    • Presenter和其他两层都是双向调用的。
    • MVP有两种实现方式:”Passive View”,View基本包含0逻辑, Presenter作为View和Model的中间人,View和Model相互隔离,View和Model没有直接的数据绑定,取而代之的是View提供相关的setter方法供Persenter去调用,这么做的好处是View和Model干净的分离开了,所以更好的进行相关测试,缺点是需要提供很多的setter方法;”Supervising Controller”,Persenter处理用户交互等的操作,View和Model直接通过数据绑定连接,这种模式下,Persenter的任务就是将实体直接通过Model层传递给View层,这种方法的好处就是代码量少了,但是缺点就是测试难度增大,并且View的封装性变低。
  • MVVM
    • 用户直接交互的是View。
    • View和ViewModel是多对一的关系。
    • View有ViewModel的引用,但是ViewModel没有任何关于View的信息。
    • 支持View和ViewModel的双向数据绑定。

6.如何设计一个靠谱MVP架构

6.1 什么是MVP?什么是MVC?

1
2
3
4
5
6
7
8
9
1、什么是MVP?
M:数据层(数据库、网络、文件存储等等...)
V:View和Activity和Fragment以及它们的子类
P:中介->Presenter(作用:将M层数据和UI层进行关联和交互中介)

2、什么是MVC?
M:单纯Model(Java Bean对象)
V:View以及子类
C:Fragment和Activity以及子类

6.2 开始进行MVP搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
内容一:MVP入门?
第一步:看一个基本案例?->普通代码实现
第二步:MVP实现->简单案例->分层次设计
第三步:MVP实现->优化->优化第1步->方法绑定
分析问题:因为当我们的Activity关闭的时候,但是网络请求还正在进行,然而我们希望是不要刷新UI了,因为销毁了,解除UI层和数据层关联?

解决方案:方法绑定(绑定、解绑)
attachView->绑定
detachView->解绑

第四步:MVP实现->优化->优化第2步->抽象
分析问题:现在写一个功能,你觉没什么,但是如果我写了20个类(写了100个类),那么你是不是要绑定(解除绑定)100次?会想死。目的就是为了不需要这么麻烦,统一管理即可(统一绑定)
解决方案:抽象类(抽象类->抽取)->BasePresenter

第五步:MVP实现->优化->优化第3步->BaseView解决
分析问题:BasePresenter类型类死了,如果你有很多的模块,那么没发抽象。然而希望动态。
解决方案:通过BaseView解决。成立

第六步:MVP实现->优化->优化第4步->泛型设计
分析问题:每一次强制类型转换,想死,一个类还好,100个类,强制类型转换100次。
解决方案:泛型设计

第七步:MVP实现->优化->优化第5步->抽象类BaseActivity->具体实现
分析问题:现在有一个Activity你需要绑定,还好,如果我有30个Activity,50个Fragment,怎么办?代码冗余?
解决方案:抽象类->抽象出绑定和解除绑定

第八步:MVP实现->优化->优化第6步->BaseActivity中抽象->抽象实现(BasePresneter和BaseView)
分析问题:父类BaseActivity写死了,还是没有满足要求?只能够用LoginPresenter_6,然而我们的目的是能够兼容所有的模块
解决方案:抽象实现(BasePresneter和BaseView)


第二步:MVP进阶?
内容二:MVP进阶?
第九步:MVP实现->优化->优化第8步->Fragment登录功能
分析问题:对Fragment进行操作(Fragment抽象)
解决方案:抽象

第十步:MVP实现->优化->优化第9步—>Fragment抽象
分析问题:对Fragment进行操作(Fragment抽象)
解决方案:抽象->泛型设计

第十一步:MVP实现->优化->优化第10步->针对LinearLayout、Button集成MVP
需求:集成->实现登录功能

第十二步:MVP实现->优化->优化第11步->抽象为一个类
分析问题:每一个模块基类都需要绑定和解除绑定,很多代码冗余。
解决方案:抽象一下(抽象为一个类)

第十三步:MVP实现->优化->优化第12步
分析问题:能够满足开发要求?针对Activity做一些处理,生命周期中控制(数据缓存、状态处理)针对Fragment做一些处理,生命周期->MVP框架进行缓存?
Activity、Fragment、View等等...处理是不一样,然而我们之前的抽象没发满足要求
解决方案:针对不同模块,针对性的处理->代理模式

6.3 优化工作介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
代理一:
代理->针对的是->MVP绑定和解绑
分析角色划分?
目标接口:绑定和解除绑定回调接口(MvpCallback)
目标对象:具体实现(ActivityCallbackImpl、FragmentCallbackImpl等等...)->Activity实现->MvpActivity
分析:创建presenter、创建view等等...
代理对象:代理实现(MvpCallbackProxy)

代理二:
代理->针对的是->Activity整体代理->生命周期代理

分析角色划分?
目标接口:ActivityMvpDelegate
目标对象:ActivityMvpDelegateImpl
代理对象:MvpActivity(Activity)

功能实现:
第一个部分:绑定和解绑->目标对象(生命周期)
第二个部分:实现MVP绑定和解绑->目标对象(MvpActivity)
第三步部分:测试