带看android-architectrue

本文将解读有名的android-architecture中的mvp相关分支
mvp是一种设计方式 ,设计方式首先要适应需求。因此, 其app建议大家先试用一下。非常简单,总共四个模块 。 但是已经基本具备了实用app的功能,其核心数据是Task, 页面主要有列表展示、详情、增加、统计。

以下会简单带大家捋一捋其思路

1.mvp (最基础的部分)

基本架构,后面的几个分支都是依托在此分支上略加修改的。
结构并不复杂,是按照模块划分的,我们主要探讨的是其中的设计模式,因此现在只保留其中的一小部分:

├── BasePresenter.java
├── BaseView.java
├── data
│   ├── Task.java
│   └── source
│       ├── TasksDataSource.java
│       ├── TasksRepository.java
├── tasks
│   ├── TasksActivity.java
│   ├── TasksContract.java
│   ├── TasksFilterType.java
│   ├── TasksFragment.java
│   └── TasksPresenter.java

其主要对应关系是:

diagram_mvp.png

(TaskRepository 扮演的是Model的角色)

熟悉mvp的同学也可以顺便参考一下其实现细节。
[1]. Activity负责Presenter和View(Fragment)的创建,也保有Presenter的实例。
[2]. 分层清晰,三个模块中只有Presenter持有Model。TasksPresenter和TaskFragment互相持有,但是只依赖了其接口(依赖倒置原则:只依赖其抽象)。
[3]. model层也负责了网络请求等。

View 层的实现非常简单,View层的实现者是Fragment来做
用例1:

#TaskPresenter.java
 @Override
    public void loadTasks(boolean forceUpdate) {
        // Simplification for sample: a network reload will be forced on first load.
        loadTasks(forceUpdate || mFirstLoad, true);
        mFirstLoad = false;
    }

    /**
     * @param forceUpdate   Pass in true to refresh the data in the {@link TasksDataSource}
     * @param showLoadingUI Pass in true to display a loading icon in the UI
     */
    private void loadTasks(boolean forceUpdate, final boolean showLoadingUI) {
        if (showLoadingUI) {
            mTasksView.setLoadingIndicator(true);
        }
        if (forceUpdate) {
            mTasksRepository.refreshTasks();
        }

        // The network request might be handled in a different thread so make sure Espresso knows
        // that the app is busy until the response is handled.
        EspressoIdlingResource.increment(); // App is busy until further notice

        mTasksRepository.getTasks(new TasksDataSource.LoadTasksCallback() {
            @Override
            public void onTasksLoaded(List<Task> tasks) {
               ...
                // The view may not be able to handle UI updates anymore
                if (!mTasksView.isActive()) {
                    return;
                }
                if (showLoadingUI) {
                    mTasksView.setLoadingIndicator(false);
                }

                processTasks(tasks);
            }

            @Override
            public void onDataNotAvailable() {
                // The view may not be able to handle UI updates anymore
                if (!mTasksView.isActive()) {
                    return;
                }
                mTasksView.showLoadingTasksError();
            }
        });
    }

用例2:

#TasksPresenter.java
@Override
    public void completeTask(@NonNull Task completedTask) {
        checkNotNull(completedTask, "completedTask cannot be null!");
        mTasksRepository.completeTask(completedTask);
        mTasksView.showTaskMarkedComplete();
        //在之后需要重新载入一次数据
        loadTasks(false, false);
    }

2.mvp-clean

我们发现,在实际的操作过程中,Presenter作为主要的逻辑处理者,到最后可能会变得非常臃肿。

而mvp-clean中就采用细化拆分的方式为Presenter瘦身。
几个用例被拆分成不同的类,分担了之前的业务逻辑代码。

image.png

UserCase的使用是比较典型的命令模式。多数同学可能对这个不太熟悉。
关于命令模式跳转
重点关注一下UserCase这个类:

public abstract class UseCase<Q extends UseCase.RequestValues, P extends UseCase.ResponseValue> {
    //请求参数被抽象
    private Q mRequestValues;
 
    // 返回结果也被抽象
    private UseCaseCallback<P> mUseCaseCallback;

    ...

    void run() {
       executeUseCase(mRequestValues);
    }

    //excute方法是命令方式一个比较明显的特征
    protected abstract void executeUseCase(Q requestValues);

    /**
     * Data passed to a request.
     */
    public interface RequestValues {
    }

    /**
     * Data received from a request.
     */
    public interface ResponseValue {
    }

    public interface UseCaseCallback<R> {
        void onSuccess(R response);
        void onError();
    }
}

这里比较新奇的是有两个空接口,RequestValue以及ResponseValue。
空接口在这里其实是语义上的声明。

另外有一点需要特别注意的是:
UseCase可能已经是业务上的最小划分了。在实际工程中遇到了两个页面需要不同的Presenter,而两个Presenter可能需要使用同一个用例。这个时候可以根据需要拼装已经写好的UseCase。
层级的划分,必然会减少重复代码。

(泡泡中遇到这种场景使用的是Helper,如对feed的点赞等。其实是一样的拆分原理。)

关于mvp-clean,其实最重要的是

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,280评论 25 709
  • 转载至:http://www.jianshu.com/p/9a6845b26856 “Android MVP 详解...
    SnowDragonYY阅读 13,489评论 5 241
  • 作者:李旺成 时间:2016年4月3日 “Android MVP 详解(下)”已经发布,欢迎大家提建议。 MVP ...
    diygreen阅读 129,206评论 85 1,321
  • [宋]陆游 红酥手,黄藤酒。满城春色宫墙柳; 东风恶,欢情薄, 一怀愁绪,几年离索, 错,错,错! 春如旧,人空瘦...
    啰唝曲阅读 3,405评论 0 0
  • 云遮皎月秋已晚,孤星夜,暖玉欠,小楼南窗寒风剪,池间蛙声一片,遥寄今宵,铭心诗卷,千年经犹转。 流芳已逝梦难断,暮...
    可有可无9527阅读 1,819评论 0 2

友情链接更多精彩内容