和 MVC 框架模式一样,Model 模型处理数据代码不变在 Android 的 App 开发中,很多人经常会头疼于 App 的架构如何设计:
本文就来带你分析一下这几个架构的特性,优缺点,以及 App 架构设计中应该注意的问题。
通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合。这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续的测试以及定位问题。但设计不能违背目的,对于不同量级的工程,具体架构的实现方式必然是不同的,切忌犯为了设计而设计,为了架构而架构的毛病。
举个简单的例子:
一个 Android App 如果只有 3 个 Java 文件,那只需要做点模块和层次的划分就可以,引入框架或者架构反而提高了工作量,降低了生产力;
但如果当前开发的 App 最终代码量在 10W 行以上,本地需要进行复杂操作,同时也需要考虑到与其余的 Android 开发者以及后台开发人员之间的同步配合,那就需要在架构上进行一些思考!
MVC 全名是 Model View Controller,如图,是模型 (model)-视图(view)-控制器(controller) 的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
其中 M 层处理数据,业务逻辑等;V 层处理界面的显示结果;C 层起到桥梁的作用,来控制 V 层和 M 层通信以此来达到分离视图显示和业务逻辑层。
Android 中界面部分也采用了当前比较流行的 MVC 框架,在 Android 中:
一般采用 XML 文件进行界面的描述,这些 XML 可以理解为 AndroidApp 的 View。使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中与界面对应的 id 不变化则代码不用修改,大大增强了代码的可维护性。
Android 的控制层的重任通常落在了众多的 Activity 的肩上。这句话也就暗含了不要在 Activity 中写代码,要通过 Activity 交割 Model 业务逻辑层处理,这样做的另外一个原因是 Android 中的 Actiivity 的响应时间是 5s,如果耗时的操作放在这里,程序就很容易被回收掉。
我们针对业务模型,建立的数据结构和相关的类,就可以理解为 AndroidApp 的 Model,Model 是与 View 无关,而与业务相关的(感谢 @Xander 的讲解)。对数据库的操作、对网络等的操作都应该在 Model 里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。
我们来看看 MVC 在 Android 开发中是怎么应用的吧!
先上界面图
Controller 控制器 & View
- publicclassMainActivityextendsActionBarActivityimplementsOnWeatherListener,View.OnClickListener {private WeatherModel weatherModel;private EditText cityNOInput;private TextView city;
- ...@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- weatherModel =new WeatherModelImpl();
- initView();
- }//初始化ViewprivatevoidinitView() {
- cityNOInput = findView(R.id.et_city_no);
- city = findView(R.id.tv_city);
- ...
- findView(R.id.btn_go).setOnClickListener(this);
- }//显示结果publicvoiddisplayResult(Weather weather) {
- WeatherInfo weatherInfo = weather.getWeatherinfo();
- city.setText(weatherInfo.getCity());
- ...
- }@OverridepublicvoidonClick(View v) {switch (v.getId()) {case R.id.btn_go:
- weatherModel.getWeather(cityNOInput.getText().toString().trim(),this);break;
- }
- }@OverridepublicvoidonSuccess(Weather weather) {
- displayResult(weather);
- }@OverridepublicvoidonError() {
- Toast.makeText(this, 获取天气信息失败, Toast.LENGTH_SHORT).show();
- }private TfindView(int id) {return (T) findViewById(id);
- }
- }
从上面代码可以看到,Activity 持有了 WeatherModel 模型的对象,当用户有点击 Button 交互的时候,Activity 作为 Controller 控制层读取 View 视图层 EditTextView 的数据,然后向 Model 模型发起数据请求,也就是调用 WeatherModel 对象的方法 getWeather()方法。当 Model 模型处理数据结束后,通过接口 OnWeatherListener 通知 View 视图层数据处理完毕,View 视图层该更新界面 UI 了。然后 View 视图层调用 displayResult()方法更新 UI。至此,整个 MVC 框架流程就在 Activity 中体现出来了。
Model 模型
来看看 WeatherModelImpl 代码实现
- publicinterfaceWeatherModel {voidgetWeather(String cityNumber, OnWeatherListener listener);
- }
- ................publicclassWeatherModelImplimplementsWeatherModel {/*这部分代码范例有问题,网络访问不应该在Model中,应该把网络访问换成从数据库读取*/@OverridepublicvoidgetWeather(String cityNumber,final OnWeatherListener listener) {/*数据层操作*/
- VolleyRequest.newInstance().newGsonRequest(http://www.weather.com.cn/data/sk/ + cityNumber + .html,
- Weather.class,new Response.Listener() {
- @OverridepublicvoidonResponse(Weather weather) {if (weather !=null) {
- listener.onSuccess(weather);
- }else {
- listener.onError();
- }
- }
- },new Response.ErrorListener() {@OverridepublicvoidonErrorResponse(VolleyError error) {
- listener.onError();
- }
- });
- }
- }
以上代码看出,这里设计了一个 WeatherModel 模型接口,然后实现了接口 WeatherModelImpl 类。controller 控制器 activity 调用 WeatherModelImpl 类中的方法发起网络请求,然后通过实现 OnWeatherListener 接口来获得网络请求的结果通知 View 视图层更新 UI 。至此,Activity 就将 View 视图显示和 Model 模型数据处理隔离开了。activity 担当 contronller 完成了 model 和 view 之间的协调作用。
至于这里为什么不直接设计成类里面的一个 getWeather()方法直接请求网络数据?你考虑下这种情况:现在代码中的网络请求是使用 Volley 框架来实现的,如果哪天老板非要你使用 Afinal 框架实现网络请求,你怎么解决问题?难道是修改 getWeather()方法的实现? no no no,这样修改不仅破坏了以前的代码,而且还不利于维护, 考虑到以后代码的扩展和维护性,我们选择设计接口的方式来解决着一个问题,我们实现另外一个 WeatherModelWithAfinalImpl 类,继承自 WeatherModel,重写里面的方法,这样不仅保留了以前的 WeatherModelImpl 类请求网络方式,还增加了 WeatherModelWithAfinalImpl 类的请求方式。Activity 调用代码无需要任何修改。
在 App 开发过程中,经常出现的问题就是某一部分的代码量过大,虽然做了模块划分和接口隔离,但也很难完全避免。从实践中看到,这更多的出现在 UI 部分,也就是 Activity 里。想象一下,一个 2000 + 行以上基本不带注释的 Activity,我的第一反应就是想吐。Activity 内容过多的原因其实很好解释,因为 Activity 本身需要担负与用户之间的操作交互,界面的展示,不是单纯的 Controller 或 View。而且现在大部分的 Activity 还对整个 App 起到类似 IOS 中的【ViewController】的作用,这又带入了大量的逻辑代码,造成 Activity 的臃肿。为了解决这个问题,让我们引入 MVP 框架。
在 Android 开发中,Activity 并不是一个标准的 MVC 模式中的 Controller,它的首要职责是加载应用的布局和初始化用户 界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity 类的职责不断增加,以致变得庞大臃肿。
MVP 从更早的 MVC 框架演变过来,与 MVC 有一定的相似性:Controller/Presenter 负责逻辑的处理,Model 提供数据,View 负责显示。
MVP 框架由 3 部分组成:View 负责显示,Presenter 负责逻辑处理,Model 提供数据。在 MVP 模式里通常包含 3 个要素(加上 View interface 是 4 个):
Tips:*View interface 的必要性
回想一下你在开发 Android 应用时是如何对代码逻辑进行单元测试的?是否每次都要将应用部署到 Android 模拟器或真机上,然后通过模拟用 户操作进行测试?然而由于 Android 平台的特性,每次部署都耗费了大量的时间,这直接导致开发效率的降低。而在 MVP 模式中,处理复杂逻辑的 Presenter 是通过 interface 与 View(Activity) 进行交互的,这说明我们可以通过自定义类实现这个 interface 来模拟 Activity 的行为对 Presenter 进行单元测试,省去了大量的部署及测试的时间。
当我们将 Activity 复杂的逻辑处理移至另外的一个类(Presenter)中时,Activity 其实就是 MVP 模式中的 View,它负责 UI 元素的初始化,建立 UI 元素与 Presenter 的关联(Listener 之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由 Presenter 处理)。
MVP 的 Presenter 是框架的控制者,承担了大量的逻辑操作,而 MVC 的 Controller 更多时候承担一种转发的作用。因此在 App 中引入 MVP 的原因,是为了将此前在 Activty 中包含的大量逻辑操作放到控制层中,避免 Activity 的臃肿。
两种模式的主要区别:
因此我们可以发现 MVP 的优点如下:
1、模型与视图完全分离,我们可以修改视图而不影响模型;
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter 内部;
3、我们可以将一个 Presenter 用于多个视图,而不需要改变 Presenter 的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁;
4、如果我们把逻辑放在 Presenter 中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。
具体到 Android App 中,一般可以将 App 根据程序的结构进行纵向划分,根据 MVP 可以将 App 分别为模型层 (M),UI 层(V) 和逻辑层(P)。
UI 层一般包括 Activity,Fragment,Adapter 等直接和 UI 相关的类,UI 层的 Activity 在启动之后实例化相应的 Presenter,App 的控制权后移,由 UI 转移到 Presenter,两者之间的通信通过 BroadCast、Handler 或者接口完成,只传递事件和结果。
举个简单的例子,UI 层通知逻辑层(Presenter)用户点击了一个 Button,逻辑层(Presenter)自己决定应该用什么行为进行响应,该找哪个模型(Model)去做这件事,最后逻辑层(Presenter)将完成的结果更新到 UI 层。
MVP 的变种有很多,其中使用最广泛的是 Passive View 模式,即被动视图。在这种模式下,View 和 Model 之间不能直接交互,View 通过 Presenter 与 Model 打交道。Presenter 接受 View 的 UI 请求,完成简单的 UI 处理逻辑,并调用 Model 进行业务处理,并调用 View 将相应的结果反映出来。View 直接依赖 Presenter,但是 Presenter 间接依赖 View,它直接依赖的是 View 实现的接口。
相对于 View 的被动,那 Presenter 就是主动的一方。对于 Presenter 的主动,有如下的理解:
转移逻辑操作之后可能部分较为复杂的 Activity 内代码量还是不少,于是需要在分层的基础上再加入模板方法(Template Method)。
具体做法是在 Activity 内部分层。其中最顶层为 BaseActivity,不做具体显示,而是提供一些基础样式,Dialog,ActionBar 在内的内容,展现给用户的 Activity 继承 BaseActivity,重写 BaseActivity 预留的方法。如有必要再进行二次继承,App 中 Activity 之间的继承次数最多不超过 3 次。
模型层(Model)中的整体代码量是最大的,一般由大量的 Package 组成,针对这部分需要做的就是在程序设计的过程中,做好模块的划分,进行接口隔离,在内部进行分层。
强化 Presenter 的作用,将所有逻辑操作都放在 Presenter 内也容易造成 Presenter 内的代码量过大,对于这点,有一个方法是在 UI 层和 Presenter 之间设置中介者 Mediator,将例如数据校验、组装在内的轻量级逻辑操作放在 Mediator 中;在 Presenter 和 Model 之间使用代理 Proxy;通过上述两者分担一部分 Presenter 的逻辑操作,但整体框架的控制权还是在 Presenter 手中。Mediator 和 Proxy 不是必须的,只在 Presenter 负担过大时才建议使用。
最终的架构如下图所示:
我们来看看 MVP 在 Android 开发中是怎么应用的吧!!
我们用另一个例子来解释。
先来看包结构图
建立 Bean
- publicclassUserBean {
- private String mFirstName;
- private String mLastName;
- publicUserBean(String firstName, String lastName) {
- this. mFirstName = firstName;
- this. mLastName = lastName;
- }
- public StringgetFirstName() {
- return mFirstName;
- }
- public StringgetLastName() {
- return mLastName;
- }
- }
建立 Model
(处理业务逻辑,这里指数据读写),先写接口,后写实现
- publicinterfaceIUserModel {voidsetID(int id);voidsetFirstName(String firstName);voidsetLastName(String lastName);intgetID();UserBeanload(int id);// 通过id读取user信息,返回一个UserBean
- }
实现不在这里写了
Presenter 控制器
建立 presenter(主导器,通过 iView 和 iModel 接口操作 model 和 view),activity 可以把所有逻辑给 presenter 处理,这样 java 逻辑就从手机的 activity 中分离出来。
- publicclassUserPresenter {private IUserView mUserView;private IUserModel mUserModel;publicUserPresenter(IUserView view) {
- mUserView = view;
- mUserModel =new UserModel();
- }publicvoidsaveUser(int id, String firstName, String lastName) {
- mUserModel.setID(id);
- mUserModel.setFirstName(firstName);
- mUserModel.setLastName(lastName);
- }publicvoidloadUser(int id) {
- UserBean user = mUserModel.load(id);
- mUserView.setFirstName(user.getFirstName());// 通过调用IUserView的方法来更新显示
- mUserView.setLastName(user.getLastName());
- }
- }
View 视图
建立 view(更新 ui 中的 view 状态),这里列出需要操作当前 view 的方法,也是接口
- publicinterfaceIUserView {intgetID();StringgetFristName();StringgetLastName();voidsetFirstName(String firstName);voidsetLastName(String lastName);
- }
activity 中实现 iview 接口,在其中操作 view,实例化一个 presenter 变量。
- publicclassMainActivityextendsActivityimplementsOnClickListener,IUserView {
- UserPresenter presenter;
- EditText id,first,last;@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
- setContentView(R.layout. activity_main);
- findViewById(R.id. save).setOnClickListener(this);
- findViewById(R.id. load).setOnClickListener(this);
- id = (EditText) findViewById(R.id. id);
- first = (EditText) findViewById(R.id. first);
- last = (EditText) findViewById(R.id. last);
- presenter =new UserPresenter(this);
- }@OverridepublicvoidonClick(View v) {switch (v.getId()) {case R.id. save:
- presenter.saveUser(getID(), getFristName(), getLastName());break;case R.id. load:
- presenter.loadUser(getID());break;default:break;
- }
- }@OverridepublicintgetID() {returnnewInteger( id.getText().toString());
- }@Overridepublic StringgetFristName() {return first.getText().toString();
- }@Overridepublic StringgetLastName() {return last.getText().toString();
- }@OverridepublicvoidsetFirstName(String firstName) {
- first.setText(firstName);
- }@OverridepublicvoidsetLastName(String lastName) {
- last.setText(lastName);
- }
- }
因此,Activity 及从 MVC 中的 Controller 中解放出来了,这会 Activity 主要做显示 View 的作用和用户交互。每个 Activity 可以根据自己显示 View 的不同实现 View 视图接口 IUserView。
通过对比同一实例的 MVC 与 MVP 的代码,可以证实 MVP 模式的一些优点:
首先介绍下 MVVM。
MVVM 可以算是 MVP 的升级版,其中的 VM 是 ViewModel 的缩写,ViewModel 可以理解成是 View 的数据模型和 Presenter 的合体,ViewModel 和 View 之间的交互通过 Data Binding 完成,而 Data Binding 可以实现双向的交互,这就使得视图和控制层之间的耦合程度进一步降低,关注点分离更为彻底,同时减轻了 Activity 的压力。
在比较之前,先从图上看看三者的异同。
刚开始理解这些概念的时候认为这几种模式虽然都是要将 view 和 model 解耦,但是非此即彼,没有关系,一个应用只会用一种模式。后来慢慢发现世界绝对不是只有黑白两面,中间最大的一块其实是灰色地带,同样,这几种模式的边界并非那么明显,可能你在自己的应用中都会用到。实际上也根本没必要去纠结自己到底用的是 MVC、MVP 还是 MVVP,不管黑猫白猫,捉住老鼠就是好猫。
MVC -> MVP -> MVVM 这几个软件设计模式是一步步演化发展的,MVVM 是从 MVP 的进一步发展与规范,MVP 隔离了 MVC 中的 M 与 V 的直接联系后,靠 Presenter 来中转,所以使用 MVP 时 P 是直接调用 View 的接口来实现对视图的操作的,这个 View 接口的东西一般来说是 showData、showLoading 等等。M 与 V 已经隔离了,方便测试了,但代码还不够优雅简洁,所以 MVVM 就弥补了这些缺陷。在 MVVM 中就出现的 Data Binding 这个概念,意思就是 View 接口的 showData 这些实现方法可以不写了,通过 Binding 来实现。
如果把这三者放在一起比较,先说一下三者的共同点,也就是 Model 和 View:
三者的差异在于如何粘合 View 和 Model,实现用户的交互操作以及变更通知
Controller 接收 View 的操作事件,根据事件不同,或者调用 Model 的接口进行数据操作,或者进行 View 的跳转,从而也意味着一个 Controller 可以对应多个 View。Controller 对 View 的实现不太关心,只会被动地接收,Model 的数据变更不通过 Controller 直接通知 View,通常 View 采用观察者模式监听 Model 的变化。
Presenter 与 Controller 一样,接收 View 的命令,对 Model 进行操作;与 Controller 不同的是 Presenter 会反作用于 View,Model 的变更通知首先被 Presenter 获得,然后 Presenter 再去更新 View。一个 Presenter 只对应于一个 View。根据 Presenter 和 View 对逻辑代码分担的程度不同,这种模式又有两种情况:Passive View 和 Supervisor Controller。
注意这里的 "Model" 指的是 View 的 Model,跟 MVVM 中的一个 Model 不是一回事。所谓 View 的 Model 就是包含 View 的一些数据属性和操作的这么一个东东,这种模式的关键技术就是数据绑定(data binding),View 的变化会直接影响 ViewModel,ViewModel 的变化或者内容也会直接体现在 View 上。这种模式实际上是框架替应用开发者做了一些工作,开发者只需要较少的代码就能实现比较复杂的交互。
MVP 和 MVVM 完全隔离了 Model 和 View,但是在有些情况下,数据从 Model 到 ViewModel 或者 Presenter 的拷贝开销很大,可能也会结合 MVC 的方式,Model 直接通知 View 进行变更。在实际的应用中很有可能你已经在不知不觉中将几种模式融合在一起,但是为了代码的可扩展、可测试性,必须做到模块的解耦,不相关的代码不要放在一起。网上有一个故事讲,一个人在一家公司做一个新产品时,一名外包公司的新员工直接在 View 中做了数据库持久化操作,而且一个 hibernate 代码展开后发现竟然有几百行的 SQL 语句,搞得他们惊讶不已,一时成为笑谈。
个人理解,在广义地谈论 MVC 架构时,并非指本文中严格定义的 MVC,而是指的 MV*,也就是视图和模型的分离,只要一个框架提供了视图和模型分离的功能,我们就可以认为它是一个 MVC 框架。在开发深入之后,可以再体会用到的框架到底是 MVC、MVP 还是 MVVM。
AOP(Aspect-Oriented Programming, 面向切面编程),诞生于上个世纪 90 年代,是对 OOP(Object-Oriented Programming, 面向对象编程) 的补充和完善。OOP 引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP 则显得无能为力。也就是说,OOP 允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(Cross-Cutting)代码,在 OOP 设计中,它导致了大量代码的重复,而不利于各个模块的重用。而 AOP 技术则恰恰相反,它利用一种称为 "横切" 的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为 "Aspect",即方面。所谓 "方面",简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。在 Android App 中,哪些是我们需要的横切关注点?个人认为主要包括以下几个方面:Http, SharedPreferences, Json, Xml, File, Device, System, Log, 格式转换等。Android App 的需求差别很大,不同的需求横切关注点必然是不一样的。一般的 App 工程中应该有一个 Util Package 来存放相关的切面操作,在项目多了之后可以将其中使用较多的 Util 封装为一个 Jar 包供工程调用。
在使用 MVP 和 AOP 对 App 进行纵向和横向的切割之后,能够使得 App 整体的结构更清晰合理,避免局部的代码臃肿,方便开发、测试以及后续的维护。
首先是作者最最喜欢的一句话,也是对创业公司特别适用的一句话,也是对不要过度设计的一种诠释:
先实现,再重构吧。直接考虑代码不臃肿得话,不知道什么时候才能写好了
先实现,再重构吧。直接考虑代码不臃肿得话,不知道什么时候才能写好了
先实现,再重构吧。直接考虑代码不臃肿得话,不知道什么时候才能写好了
(重要的事情说三遍)
代码和文档规范,根据需求进行模块划分,确定交互方式,形成接口文档,这些较为通用的内容不再细说。做 Android App 时,一般将 App 进行纵向和横向的划分。纵向的 App 由 UI 层,逻辑层和模型层构成,整体结构基于 MVP 思想 (图片来自网络)。
UI 层内部多用模板方法,以 Activity 为例一般有 BaseActivity,提供包括一些基础样式,Dialog,ActionBar 在内的内容,展现的 Activity 都会继承 BaseActivity 并实现预留的接口,Activity 之间的继承不超过 3 次;为避免 Activity 内代码过多,将 App 的整体控制权后移,也借鉴了 IOC 做法,大量的逻辑操作放在逻辑层中,逻辑层和 UI 层通过接口或者 Broadcast 等实现通信,只传递结果。一般 Activity 里的代码量都很大,通过这两种方式一般我写的单个 Activity 内代码量不超过 400 行。
逻辑层实现的是绝大部分的逻辑操作,由 UI 层启动,在内部通过接口调用模型层的方法,在逻辑层内大量使用了代理。打个比方,UI 层告诉逻辑层我需要做的事,逻辑层去找相应的人 (模型层) 去做,最后只告诉 UI 这件事做的结果。
模型层没什么好说的,这部分一般由大量的 Package 组成,代码量是三层中最大的,需要在内部进行分层。
横向的分割依据 AOP 面向切面的思想,主要是提取出共用方法作为一个单独的 Util,这些 Util 会在 App 整体中穿插使用。很多人的 App 都会引入自己封装的 Jar 包,封装了包括文件、JSON、SharedPreference 等在内的常用操作,自己写的用起来顺手,也大幅度降低了重复作业。
这样纵,横两次对于 App 代码的分割已经能使得程序不会过多堆积在一个 Java 文件里,但靠一次开发过程就写出高质量的代码是很困难的,趁着项目的间歇期,对代码进行重构很有必要。
现在有很多帮助快速开发的类库,活用这些类库也是避免代码臃肿和混乱的好方法,下面给题主推荐几个常用类库。
减少 Activity 代码量的依赖注入框架 ButterKnife:
https://github.com/JakeWharton/butterknife
简化对于 SQlite 操作的对象关系映射框架 OrmLite:
https://github.com/j256/ormlite-android
图片缓存类库 Fresco(by facebook):
https://github.com/facebook/fresco
能用第三方库就用第三方库。别管是否稳定,是否被持续维护,因为,任何第三方库的作者,都能碾压刚入门的菜鸟,你绝对写不出比别人更好的代码了。
最后附上知乎上面点赞次数很高的一段话:
如果 "从零开始",用什么设计架构的问题属于想得太多做得太少的问题。
从零开始意味着一个项目的主要技术难点是基本功能实现。当每一个功能都需要考虑如何做到的时候,我觉得一般人都没办法考虑如何做好。
因为,所有的优化都是站在最上层进行统筹规划。在这之前,你必须对下层的每一个模块都非常熟悉,进而提炼可复用的代码、规划逻辑流程。
所以,如果真的是从零开始,别想太多了
参考文献:
1、http://blog.csdn.net/luyi325xyz/article/details/43085409
2、http://blog.csdn.net/napolunyishi/article/details/22722345
3、https://www.zhihu.com/question/27645587/answer/37579829
4、http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0202/2397.html
5、http://www.tuicool.com/articles/VJZrYb
6、https://www.zhihu.com/question/27645587
7、http://blog.csdn.net/luyi325xyz/article/details/43482123
8、https://www.zhihu.com/question/30976423
9、http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0313/2599.html
10、http://www.2cto.com/kf/201506/405766.html
11、https://www.zhihu.com/question/19766132
12、http://www.cnblogs.com/artech/archive/2010/03/25/1696205.html
13、https://segmentfault.com/a/1190000003927200
14、http://blog.csdn.net/knxw0001/article/details/39637273
相关:
android MVC && MVP && MVVM 分析和对比来源: http://blog.csdn.net/guofengpu/article/details/72780151