MVC、MVP 和 MVVM 是常见的三种架构设计模式,当前 MVP 和 MVVM 的使用相对比较广泛,当然 MVC 也并没有过时之说。而所谓的组件化就是指将应用根据业务需求划分成各个模块来进行开发,每个模块又可以编译成独立的APP进行开发。理论上讲,组件化和前面三种架构设计不是一个层次的。它们之间的关系是,组件化的各个组件可以使用前面三种架构设计。我们只有了解了这些架构设计的特点之后,才能在进行开发的时候选择适合自己项目的架构模式,这也是本文的目的。
1、MVC
MVC (Model-View-Controller, 模型-视图-控制器),标准的 MVC 是这个样子的:
-
模型层 (Model):业务逻辑对应的数据模型,无 View 无关,而与业务相关;
-
视图层 (View):一般使用 XML 或者 Java 对界面进行描述;
-
控制层 (Controllor):在 Android 中通常指 Activity 和 Fragment,或者由其控制的业务类。
Activity 并非标准的 Controller,它一方面用来控制了布局,另一方面还要在 Activity 中写业务代码,造成了 Activity 既像 View 又像Controller。
在 Android 开发中,就是指直接使用 Activity 并在其中写业务逻辑的开发方式。显然,一方面 Activity 本身就是一个视图,另一方面又要负责处理业务逻辑,因此逻辑会比较混乱。
这种开发方式不太适合 Android 开发。
2、MVP
2.1 概念梳理
MVP (Model-View-Presenter) 是 MVC 的演化版本,几个主要部分如下:
-
模型层 (Model):主要提供数据存取功能。
-
视图层 (View):处理用户事件和视图。在 Android 中,可能是指 Activity、Fragment 或者 View。
-
展示层 (Presenter):负责通过 Model 存取数据,连接 View 和 Model,从 Model 中取出数据交给 View。
所以,对于 MVP 的架构设计,我们有以下几点需要说明:
-
这里的 Model 是用来存取数据的,也就是用来从指定的数据源中获取数据,不要将其理解成 MVC 中的 Model。在 MVC 中 Model 是数据模型,在 MVP 中,我们用 Bean 来表示数据模型。
-
Model 和 View 不会直接发生关系,它们需要通过 Presenter 来进行交互。在实际的开发中,我们可以用接口来定义一些规范,然后让我们的 View 和 Model 实现它们,并借助 Presenter 进行交互即可。
为了说明 MVP 设计模式,我们给出一个示例程序。你可以在 Android-references 中获取到它的源代码。
2.2 示例程序
在该示例中,我们使用了:
-
开眼视频的 API 作为数据源;
-
Retrofit 进行数据访问;
-
使用 ARouter 进行路由;
-
使用 MVP 设计模式作为程序架构。
下面是该模块的基本的包结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3OsWwKEl-1614135815610)(https://upload-images.jianshu.io/upload_images/23587538-2db584291d462157?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 “包结构”)]
这里核心的代码是 MVP 部分。
这里我们首先定义了 MVP 模式中的最顶层的 View 和 Presenter,在这里分别是 BaseView
和 BasePresenter
,它们在该项目中是两个空的接口,在一些项目中,我们可以根据自己的需求在这两个接口中添加自己需要的方法。
然后,我们定义了 HomeContract
。它是一个抽象的接口,相当于一层协议,用来规定指定的功能的 View 和 Presenter 分别应该具有哪些方法。通常,对于不同的功能,我们需要分别实现一个 MVP,每个 MVP 都会有一个对应的 Contract。笔者认为它的好处在于,将指定的 View 和 Presenter 的接口定义在一个接口中,更加集中。它们各自需要实现的方法也一目了然地展现在了我们面前。
这里根据我们的业务场景,该接口的定义如下:
public interface HomeContract {
interface IView extends BaseView {
void setFirstPage(List<HomeBean.IssueList.ItemList> itemLists);
void setNextPage(List<HomeBean.IssueList.ItemList> itemLists);
void onError(String msg);
}
interface IPresenter extends BasePresenter {
void requestFirstPage();
void requestNextPage();
}
}
HomeContract
用来规定 View 和 Presenter 应该具有的操作,在这里它用来指定主页的 View 和 Presenter 的方法。从上面我们也可以看出,这里的 IView
和 IPresenter
分别实现了 BaseView
和 BasePresenter
。
上面,我们定义了 V 和 P 的规范,MVP 中还有一项 Model,它用来从网络中获取数据。这里我们省去网络相关的具体的代码,你只需要知道 APIRetrofit.getEyepetizerService()
是用来获取 Retrofit 对应的 Service,而 getMoreHomeData()
和 getFirstHomeData()
是用来从指定的接口中获取数据就行。下面是 HomeModel
的定义:
public class HomeModel {
public Observable<HomeBean> getFirstHomeData() {
return APIRetrofit.getEyepetizerService().getFirstHomeData(System.currentTimeMillis());
}
public Observable<HomeBean> getMoreHomeData(String url) {
return APIRetrofit.getEyepetizerService().getMoreHomeData(url