您的位置:首页 > 运维架构 > 网站架构

[译]Google官方关于Android架构中MVP模式的示例

2016-11-19 17:38 465 查看

概述

该示例(TODO-MVP)是后续各种示例演变的基础,它主要演示了在不带架构性框架的情况下实现M-V-P模式。其采用手动依赖注入的方式来提供本地数据源和远程数据源仓库。异步任务通过回调处理。



注意:MVP中View的概念是有所不同的:

android.view.View类我们叫它 "Android View"

MVP中从P接收命令的东西我们叫它”View”,后文说了,就是Fragment

Fragment

采用Fragment作为视图的载体有两个原因:

Activity 和 Fragment分离恰好适合用来实现MVP:Activity是创建和连接View与Presenter的总控制器

适配平板设备的布局或多视图屏幕的场景都可利用Fragment框架的优势

关键概念

该App(指官方TODO-MVP示例)中有四个功能:

Tasks

TaskDetail

AddEditTask

Statistics

每个功能拥有下列代码分工:

定义VIew和Presenter之间的“契约”接口

一个Activity类负责创建Fragment和Presenter

一个Fragment类实现VIew接口

一个Presenter类实现Presenter接口

一般来说,业务逻辑存在于Presenter中并依赖View完成Android中UI相关的工作。

View中几乎不包含逻辑:它将Presenter的命令转换为UI动作,并监听用户动作传递给Presenter。

“契约”接口用于定义View和Presenter之间的联系。

(译注:

有人立马就问到M哪去了,官方实例里M是轻的,与Repository和DataSource概念分离。在官方的另一个示例中有进一步的描述:http://www.cnblogs.com/x3d/p/6108998.html

/**
* Immutable model class for a Task.
*/
public final class Task {

@NonNull
private final String mId;

@Nullable
private final String mTitle;

@Nullable
private final String mDescription;

private final boolean mCompleted;

@NonNull
public String getId() {
return mId;
}

@Nullable
public String getTitle() {
return mTitle;
}

@Nullable
public String getTitleForList() {
if (!Strings.isNullOrEmpty(mTitle)) {
return mTitle;
} else {
return mDescription;
}
}

@Nullable
public String getDescription() {
return mDescription;
}

public boolean isCompleted() {
return mCompleted;
}

public boolean isActive() {
return !mCompleted;
}

public boolean isEmpty() {
return Strings.isNullOrEmpty(mTitle) &&
Strings.isNullOrEmpty(mDescription);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Task task = (Task) o;
return Objects.equal(mId, task.mId) &&
Objects.equal(mTitle, task.mTitle) &&
Objects.equal(mDescription, task.mDescription);
}

@Override
public int hashCode() {
return Objects.hashCode(mId, mTitle, mDescription);
}

@Override
public String toString() {
return "Task with title " + mTitle;
}

}

DataSource、Repository相关代码布局:



契约接口定义:

package com.example.android.architecture.blueprints.todoapp.taskdetail;

import com.example.android.architecture.blueprints.todoapp.BasePresenter;
import com.example.android.architecture.blueprints.todoapp.BaseView;

/**
* This specifies the contract between the view and the presenter.
*/
public interface TaskDetailContract {

interface View extends BaseView<Presenter> {

void setLoadingIndicator(boolean active);

void showMissingTask();

void hideTitle();

void showTitle(String title);

void hideDescription();

void showDescription(String description);

void showCompletionStatus(boolean complete);

void showEditTask(String taskId);

void showTaskDeleted();

void showTaskMarkedComplete();

void showTaskMarkedActive();

boolean isActive();
}

interface Presenter extends BasePresenter {

void editTask();

void deleteTask();

void completeTask();

void activateTask();
}
}

)

项目依赖

Common Android support 库 (com.android.support.*)

Android Testing Support 库 (Espresso, AndroidJUnitRunner…)

Mockito

Guava (null checking)

特性

复杂度 - 易理解性

使用架构性框架/库/工具类:



概念复杂度

低,基于Android的纯MVP实现。

可测试性

单元测试

高,Presenter可被单元测试,和仓库与数据源一样。

UI 测试

高,允许使用fake模块注入伪造(fake)数据进行测试。

代码对比

相比于不使用架构的传统项目,该示例引入了额外的类和接口:Presenter、Repositiy、契约接口等,所以MVP中代码行数更多一些。

语言文件空行注释代码
Java46107514513451
XML3497337601
SUM80117217884052

可维护性

简化功能的维护或新功能的迭代



学习成本



相关功能代码能容易查找定位、代码职责清晰。开发者无需熟悉任何外部的依赖就能对该项目开展工作。

Github项目地址:https://github.com/googlesamples/android-architecture/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: