乐趣区

关于html5:Android开发中的MVP架构

最近越来越多的人开始议论架构。我四周的共事和工程师也是如此。只管我还不是特地深刻了解 MVP 和 DDD,然而咱们的新我的项目还是决定通过 MVP 来构建。

这篇文章是我通过钻研和学习各种文章以及专题讨论所总结进去的,它包含以下几点:

为什么越来越多的人开始关注架构?

首先,MVP 是什么?

哪种架构才是最好的,MVC,MVVM 还是 MVP?

MVP 的利与弊

Show me the code!!! 代码展现

可怜的,这篇文章将不包含:

具体活泼的代码示例

如何编写测试代码

最初,我将通知你如何更进一步学习这些专题。

顺便提一下,我于上周在当地的一个研讨会上对 MVP 架构进行了相干演讲。这篇文章与过后的演讲内容相差无几。

介绍~Activity 是上帝类~
首先,让咱们思考一下为什么在 Android 开发中如此迫切地须要一个清晰的软件架构。

该段摘自“代码大全第二版”:

防止创立神类。防止创立无所不知,无所不能的上帝类。如果一个类须要破费工夫从其余类中通过 Get()和 Set()检索数据(也就是说,须要深刻业务并且通知它们如何去做),所以是否应该把这些性能函数更好的组织到其它类而不是上帝类中。(Riel 1996)

上帝类的保护老本很高,你很难了解正在进行的操作,并且难以测试和扩大,这就是为什么要防止创立上帝类的黄金法令。

然而,在 Android 开发中,如果你不思考架构的话,Activity 类往往会越来越大。这是因为,在 Android 中,容许 View 和其它线程共存于 Activity 内。其实最大的问题莫过于在 Activity 中同时存在业务逻辑和 UI 逻辑。这会减少测试和保护的老本。

图片

这是为什么须要清晰架构的起因之一。不仅会造成 Activity 的臃肿,还会引起其余问题,如使 Activity 和 Fragment 的生命周期变简单,以及数据绑定等。

什么是 MVP?
MVP 代表 Model,View 和 Presenter。

View 层负责解决用户事件和视图局部的展现。在 Android 中,它可能是 Activity 或者 Fragment 类。

Model 层负责拜访数据。数据能够是远端的 Server API,本地数据库或者 SharedPreference 等。

Presenter 层是连贯(或适配)View 和 Model 的桥梁。

下图是基于 MVP 架构的模式之一。View 是 UI 线程。Presenter 是 View 与 Model 之间的适配器。UseCase 或者 Domain 在 Model 层中,负责从实体获取或载入数据。依赖规定如下:

图片
要害是,高层接口不晓得底层接口的细节,或者更精确地说,高层接口不能,不应该,并且必须不理解底层接口的细节,是(面向)形象的,并且是细节暗藏的。

图片

依赖规定?
Uncle Bob 的“The Clean Architecture”形容了依赖的规定是什么。

同心圆将软件划分为不同的区域,个别的,随着层级的深刻,软件的等级也就越高。外圆是实现机制,内圆是外围策略。

这是下面片文章的摘要:

Entities:

能够是一个持有办法函数的对象

能够是一组数据结构或办法函数

它并不重要,能在我的项目中被不同应用程序应用即可

Use Cases

蕴含特定于应用程序的业务规定

精心编排流入 Entity 或从 Entity 流出的数据

指挥 Entity 间接应用我的项目范畴内的业务规定,从而实现 Use Case 的指标

Presenters,,Controllers

将 Use Case 和 Entity 中的数据转换成格局最不便的数据

内部零碎,如数据库或网页可能不便的应用这些数据

齐全蕴含 GUI 的 MVC 架构

External Interfaces, UI, DB

所有的细节所在

如数据库细节,Web 框架细节,等等

MVC,MVP 还是 MVVM?
那么,哪一个才是最好的呢?哪一个比其余的更优良呢?我能只抉择一个吗?

答案是,NO。

这些模式的动机都是一样的。那就是如何防止简单凌乱的代码,让执行单元测试变得容易,发明高质量应用程序。就这样。

当然,远不止这三种架构模式。而且任何一种模式都不可能是银弹,他们只是架构模式之一,不是解决问题的惟一路径。这些只是办法、伎俩而不是目标、指标。

利与弊
OK,让咱们回到 MVP 架构上。刚刚咱们理解了什么是 MVP,探讨了 MVP 以及其它热门架构,并且介绍了 MVC,MVP 和 MVVM 三者间的不同。这是对于 MVP 架构利与弊的总结:

** 利

可测试(TDD)

可保护(代码复用)

容易 Reviewe

信息隐蔽

** 弊

冗余的,尤其是小型 App 开发

(有可能)额定的学习曲线

开始编写代码之前须要工夫老本(然而我敢打赌,设计架构是所有我的项目开发所必须的)

Show me the code!!!
这里仅展现了 MVP 模式的一小段构造。如果你想理解更多我的项目或活泼的代码示例,请参考文章开端的“链接和资源”。那里有十分丰盛和设计奇妙的示例,根本都托管在 Github 上,以便你能 clone,在设施上运行,并理解工作原理。

首先,为每一个 View 定义接口。

/**

  • Interface classes for the Top view

*/

public interface TopView {

/**

 * Initialize the view.

 * 

 * e.g. the facade-pattern method for handling all Actionbar settings

 */

void initViews();



/**

 * Open {@link DatePickerDialog}

 */

void openDatePickerDialog();



/**

 * Start ListActivity

 */

void startListActivity();

}

让咱们重写 TopView 类,要点如下:

TopActivity 只是负责处理事件监听或者展现每个视图组件

所有的业务逻辑必须委托给 Presenter 类

在 MVP 中,View 和 Presenter 游戏是一 一对应的(在 MVVM 中是一对多的)

public class TopActivity extends Activity implements TopView {

// here we use ButterKnife to inject views

/**

  • Calendar Title

*/

@Bind(R.id.calendar_title)

TextView mCalendarTitle;

private TopPresenter mTopPresenter;

@Override

protected void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.activity_top);

  ButterKnife.bind(this);



  // Save TopPresenter instance in a meber variable field

  mTopPresenter = new TopPresenter();

  mTopPresenter.onCreate(this);

}

/*

  • Overrides method fromwww.sangpi.com the {@link TopView} interfaces

*/

@Override

public void initViews() {

  // Actionbar settins



  // set event listeners

}

@Override

public void openDatePickerDialog() {

  DatePickerFragment.newInstance().show(getSupportFragmentManager(),

          DatePickerFragment.TAG);



  // do not write logic here... all logic must be passed to the Presenter

  mTopPresenter.updateCalendarDate();

}

@Override

public void startListActivity() {

  startActivity(new Intent(this, ListActivity.class));

}

}

这是 Presenter 类,最重要的一点是 Presenter 仅仅是连贯 View 与 Model 的适配桥梁。比方,TopUseCase#saveCalendarDate()是对 TopPresenter 细节暗藏的,同样对 TopView 也是如此。你不须要关怀数据结构,也不须要关怀业务逻辑是如何工作的。因而你能够对 TopUseCase 执行单元测试,因为业务逻辑与视图层是拆散的。

public class TopPresenter {

@Nullable

private TopView mView;



private TopUseCase mUseCase;



public TopPresenter() {mUseCase = new TopUseCase();

}



public void onCreate(@NonNull TopView topView) {

    mView = topView;



    // here you call View's implemented methods

    mView.initViews();}



public void updateCalendarDate() {

    // do not forget to return if view instances is null

    if (mView == null) {return;}



    // here logic comes

    String dateToDisplay = mUseCase.getDateToDisplay(mContext.getResources());

    mView.updateCalendarDate(dateToDisplay);



    // here you save date, and this logic is hidden in UseCase class

    mUseCase.saveCalendarDate();}

}

当然,只管业务逻辑被实现在 Activity 类中,你仍然能够执行单元测试,只不过这会消耗很多工夫,而且有些简单。可能须要更多的工夫来运行 App,相同,你本应该充分利用测试类库的性能,如 Robolectric。

总结
这里没有万能药,而且 MVP 也仅仅是解决方案之一,它能够与其余办法协同应用,同样,也能够有抉择的用于不同我的项目。

退出移动版