Android官方架構(gòu)項(xiàng)目之MVP + Clean

首先,不了解 Clean 架構(gòu)的可以看看這個(gè),不過也沒關(guān)系,閱讀本文后你也許會(huì)對(duì)Clean架構(gòu)思想有一個(gè)認(rèn)識(shí)。

對(duì)比MVP項(xiàng)目的結(jié)構(gòu)圖,我們發(fā)現(xiàn)不同之處是新增的這個(gè)Domain Layer這層,來隔離Presentation Layer和Data Layer,負(fù)責(zé)了所有的業(yè)務(wù)邏輯交互,那么本文就主要來分析這層的設(shè)計(jì)和實(shí)現(xiàn)。

MVP-Clean架構(gòu)圖

我們?nèi)匀灰許ample中詳情界面(功能)來進(jìn)行分析,下圖展示了在 TaskDetailFragment 中點(diǎn)擊刪除按鈕,然后所經(jīng)歷的邏輯交互以及最后完成了界面更新。


時(shí)序圖

1、在 TaskDetailFragment 中點(diǎn)擊菜單,調(diào)用 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 對(duì)象來執(zhí)行任務(wù),并處理結(jié)果和異常。

    // 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 類中維護(hù)了 UseCaseThreadPoolScheduler 的示例對(duì)象,在其中定義了 ThreadPoolExecutor 來執(zhí)行異步任務(wù),任務(wù)的結(jié)果回調(diào)則使用 Handler post的方式來切換到主線程。

    // UseCaseHandler 中初始化 UseCaseThreadPoolScheduler 對(duì)象
    public static UseCaseHandler getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new UseCaseHandler(new UseCaseThreadPoolScheduler());
        }
        return INSTANCE;
    }

    // UseCaseThreadPoolScheduler 中定義了 ThreadPoolExecutor 對(duì)象
    public UseCaseThreadPoolScheduler() {
        mThreadPoolExecutor = new ThreadPoolExecutor(POOL_SIZE, MAX_POOL_SIZE, TIMEOUT,
                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(POOL_SIZE));
    }

    // 并執(zhí)行異步任務(wù)
    @Override
    public void execute(Runnable runnable) {
        mThreadPoolExecutor.execute(runnable);
    }

    // response使用Handler來處理結(jié)果回調(diào)
    @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 中其實(shí)還是調(diào)用 UseCase 的 run() 方法,而 UseCase 的 executeUseCase() 是抽象方法,最終邏輯是由各個(gè)Task子類實(shí)現(xiàn)的,比如 DeleteTask:

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

從以上的分析流程中可以看出,原本位于 Presenter 中的業(yè)務(wù)邏輯轉(zhuǎn)移到了 UseCaseHandler 中,UseCaseHandler 使用 UseCaseScheduler 來切換工作線程和UI線程,使用 UseCase 來處理每個(gè) Task 的邏輯。其類圖如下:

UML類圖

** 總結(jié) **

  • 與MVP最大的不同是加入了 Domain layer 和 use cases,把原本位于 Presenter 中臃腫的邏輯代碼移到了 Domain layer 中,減輕了 Presenter 的體量,而 use cases 定義了每個(gè)業(yè)務(wù)的具體操作,細(xì)化了業(yè)務(wù)粒度,也有效提高了代碼的重用性。
  • 使用 UseCaseScheduler 來提供線程池執(zhí)行異步任務(wù),并可以切換工作線程和UI線程。

轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://m.itdecent.cn/p/7ae3095f2cb5

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容