zoukankan      html  css  js  c++  java
  • [译]Google官方关于Android架构中MVP模式的示例

    概述

    该示例(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中代码行数更多一些。

    语言 文件 空行 注释 代码
    Java 46 1075 1451 3451
    XML 34 97 337 601
    SUM 80 1172 1788 4052

    可维护性

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

    学习成本

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

    Github项目地址:https://github.com/googlesamples/android-architecture/

  • 相关阅读:
    ssh认证
    Nginx中proxy_pass 后有无/的区别
    Nginx中$http_host、$host、$proxy_host的区别
    Nginx读书笔记----HTTP proxy module
    ngx_http_core_module模块提供的变量
    Nginx读书笔记三----资源分配
    http_code 413 Request Entity Too Large
    nginx读书笔记二----nginx配置
    firewall-cmd命令
    GCC编译器原理(一)03------GCC 工具:gprof、ld、libbfd、libiberty 和libopcodes
  • 原文地址:https://www.cnblogs.com/x3d/p/android-mvp.html
Copyright © 2011-2022 走看看