• 【转】Android官方架构项目之MVP + Clean


    首先,不了解 Clean 架构的可以看看这个,不过也没关系,阅读本文后你也许会对Clean架构思想有一个认识。

    对比MVP项目的结构图,我们发现不同之处是新增的这个Domain Layer这层,来隔离Presentation Layer和Data Layer,负责了所有的业务逻辑交互,那么本文就主要来分析这层的设计和实现。

     
    MVP-Clean架构图

    我们仍然以Sample中详情界面(功能)来进行分析,下图展示了在 TaskDetailFragment 中点击删除按钮,然后所经历的逻辑交互以及最后完成了界面更新。


     
    时序图

    1、在 TaskDetailFragment 中点击菜单,调用 Presenter 的 deleteTask() 方法:

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.menu_delete:
                    mPresenter.deleteTask();
                    return true;
            }
            return false;
        }
    

    2、Presenter 的 deleteTask() 方法,是使用UseCaseHandler类中的 UseCaseScheduler 对象来执行任务,并处理结果和异常。

        // TaskDetailPresenter 中deleteTask() 方法
        @Override
        public void deleteTask() {
            mUseCaseHandler.execute(mDeleteTask, new DeleteTask.RequestValues(mTaskId),
                    new UseCase.UseCaseCallback<DeleteTask.ResponseValue>() {
                        @Override
                        public void onSuccess(DeleteTask.ResponseValue response) {
                            mTaskDetailView.showTaskDeleted();
                        }
    
                        @Override
                        public void onError(Error error) {
                            // Show error, log, etc.
                        }
                    });
        }
    
        // UseCaseHandler 中 execute() 方法
        public <T extends UseCase.RequestValues, R extends UseCase.ResponseValue> void execute(
                final UseCase<T, R> useCase, T values, UseCase.UseCaseCallback<R> callback) {
            useCase.setRequestValues(values);
            useCase.setUseCaseCallback(new UiCallbackWrapper(callback, this));
    
            // 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
    
            mUseCaseScheduler.execute(new Runnable() {
                @Override
                public void run() {
                    useCase.run();
                    // This callback may be called twice, once for the cache and once for loading
                    // the data from the server API, so we check before decrementing, otherwise
                    // it throws "Counter has been corrupted!" exception.
                    if (!EspressoIdlingResource.getIdlingResource().isIdleNow()) {
                        EspressoIdlingResource.decrement(); // Set app as idle.
                    }
                }
            });
        }
    

    3、UseCaseHandler 类中维护了 UseCaseThreadPoolScheduler 的示例对象,在其中定义了 ThreadPoolExecutor 来执行异步任务,任务的结果回调则使用 Handler post的方式来切换到主线程。

        // UseCaseHandler 中初始化 UseCaseThreadPoolScheduler 对象
        public static UseCaseHandler getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new UseCaseHandler(new UseCaseThreadPoolScheduler());
            }
            return INSTANCE;
        }
    
        // UseCaseThreadPoolScheduler 中定义了 ThreadPoolExecutor 对象
        public UseCaseThreadPoolScheduler() {
            mThreadPoolExecutor = new ThreadPoolExecutor(POOL_SIZE, MAX_POOL_SIZE, TIMEOUT,
                    TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(POOL_SIZE));
        }
    
        // 并执行异步任务
        @Override
        public void execute(Runnable runnable) {
            mThreadPoolExecutor.execute(runnable);
        }
    
        // response使用Handler来处理结果回调
        @Override
        public <V extends UseCase.ResponseValue> void notifyResponse(final V response,
                final UseCase.UseCaseCallback<V> useCaseCallback) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    useCaseCallback.onSuccess(response);
                }
            });
        }
    

    4、UseCaseHandler 中其实还是调用 UseCase 的 run() 方法,而 UseCase 的 executeUseCase() 是抽象方法,最终逻辑是由各个Task子类实现的,比如 DeleteTask:

        @Override
        protected void executeUseCase(final RequestValues values) {
            mTasksRepository.deleteTask(values.getTaskId());
            getUseCaseCallback().onSuccess(new ResponseValue());
        }
    

    从以上的分析流程中可以看出,原本位于 Presenter 中的业务逻辑转移到了 UseCaseHandler 中,UseCaseHandler 使用 UseCaseScheduler 来切换工作线程和UI线程,使用 UseCase 来处理每个 Task 的逻辑。其类图如下:

     
    UML类图

    ** 总结 **

    • 与MVP最大的不同是加入了 Domain layer 和 use cases,把原本位于 Presenter 中臃肿的逻辑代码移到了 Domain layer 中,减轻了 Presenter 的体量,而 use cases 定义了每个业务的具体操作,细化了业务粒度,也有效提高了代码的重用性。
    • 使用 UseCaseScheduler 来提供线程池执行异步任务,并可以切换工作线程和UI线程。

    转载请标明出处:http://www.jianshu.com/p/7ae3095f2cb5



    作者:spiritTalk
    链接:https://www.jianshu.com/p/7ae3095f2cb5
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    HTML学习基础(一)
    初识C#
    SQL小知识
    jQuery(四)
    jQuery(三)
    认识jQuery(二)
    认识Jquery
    初识Javascript
    初识HTML
    博客,你好!
  • 原文地址:https://www.cnblogs.com/didiaoxiong/p/9104896.html
Copyright © 2020-2023  润新知