Google官方MVP腦補

一、組成


下面一張圖勝過千言萬語


用一句話來概括,就說P將M和V分開了,其實也沒這麼簡單,P會將自己傳遞給V,然後在V中進行一些邏輯


二、分析


如下是Google官方基礎MVP程序的框架


我們發現在主包下面有6個子包和兩個接口

  • addedittask:添加修改界面
  • data:數據源
  • statistics:統計界面
  • taskdetail:Todo item 詳情頁見面
  • tasks:Todo 事件列表界面(主界面)
  • util:幫助工具類
  • BasePresenter、BaseView:presenter、view接口基類

我們發現關鍵概念裏面講的4個屬性就是這裏面的4個子包,並且這4個子包有很大的相似性,它們都有下面4個接口或者類

  • Contract
  • Activity
  • Fragment
  • Presenter

三、代碼



下面以taskdetail爲例子來進行代碼的分析

(1)TaskDetailContract

這是一個合同類,其中包含了兩個接口,一個是View,一個是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();
    }
}

(2)TaskDetailActivity

可以看到在Activity中主要實現了兩大功能,一個是Fragment也就是View的初始化,另一個就是Presenter的初始化,在Presenter的初始化過程中需要傳入兩個參數,一個是View,一個是數據庫操作類,這同時也說明了Presenter對V和M的連通行。

public class TaskDetailActivity extends AppCompatActivity {

    public static final String EXTRA_TASK_ID = "TASK_ID";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.taskdetail_act);

        // Set up the toolbar.
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ActionBar ab = getSupportActionBar();
        ab.setDisplayHomeAsUpEnabled(true);
        ab.setDisplayShowHomeEnabled(true);

        // Get the requested task id
        String taskId = getIntent().getStringExtra(EXTRA_TASK_ID);

        TaskDetailFragment taskDetailFragment = (TaskDetailFragment) getSupportFragmentManager()
                .findFragmentById(R.id.contentFrame);

        if (taskDetailFragment == null) {
            taskDetailFragment = TaskDetailFragment.newInstance(taskId);

            ActivityUtils.addFragmentToActivity(getSupportFragmentManager(),
                    taskDetailFragment, R.id.contentFrame);
        }

        // Create the presenter
        new TaskDetailPresenter(
                taskId,
                Injection.provideTasksRepository(getApplicationContext()),
                taskDetailFragment);
    }

    @Override
    public boolean onSupportNavigateUp() {
        onBackPressed();
        return true;
    }
}


(3)TaskDetailPersenter

終於到了Persenter了,這個傢伙的邏輯應該是很複雜吧,畢竟要實現M和V的橋樑作用,但是這裏只是實現來一些方法,這些方法是用來操作數據庫和View的,其中數據庫和View的具體實現方法還是由其自己來實現。

因此這裏的邏輯並不複雜,最關鍵的一個地方就是通過mTaskDetailView.setPresenter(this)方法將自己傳遞到View中

這裏的mTaskDetailView是通過參數傳遞進來的,代碼太多了,所以精簡一下

public class TaskDetailPresenter implements TaskDetailContract.Presenter {

    public TaskDetailPresenter(@Nullable String taskId,
                               @NonNull TasksRepository tasksRepository,
                               @NonNull TaskDetailContract.View taskDetailView) {
        mTaskId = taskId;
        mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null!");
        mTaskDetailView = checkNotNull(taskDetailView, "taskDetailView cannot be null!");

        mTaskDetailView.setPresenter(this);
    }

    @Override
    public void start() {
        openTask();
    }

    private void openTask() {
    }

    @Override
    public void editTask() {
        if (Strings.isNullOrEmpty(mTaskId)) {
            mTaskDetailView.showMissingTask();
            return;
        }
        mTaskDetailView.showEditTask(mTaskId);
    }

    @Override
    public void deleteTask() {
        if (Strings.isNullOrEmpty(mTaskId)) {
            mTaskDetailView.showMissingTask();
            return;
        }
        mTasksRepository.deleteTask(mTaskId);
        mTaskDetailView.showTaskDeleted();
    }

    @Override
    public void completeTask() {
    }

    @Override
    public void activateTask() {
    }

    private void showTask(@NonNull Task task) {

    }
}

(4)TaskDetailFragment

我們在Fragment中獲得了Presenter的對象,這樣可以就可以調用Presenter的方法,然後通過Persenter來調用M和V的方法,這樣就可以實現用P來控制M和V了。

以下是部分程序:

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.taskdetail_frag, container, false);
        setHasOptionsMenu(true);
        mDetailTitle = (TextView) root.findViewById(R.id.task_detail_title);
        mDetailDescription = (TextView) root.findViewById(R.id.task_detail_description);
        mDetailCompleteStatus = (CheckBox) root.findViewById(R.id.task_detail_complete);

        // Set up floating action button
        FloatingActionButton fab =
                (FloatingActionButton) getActivity().findViewById(R.id.fab_edit_task);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.editTask();
            }
        });

        return root;
    }

    @Override
    public void setPresenter(@NonNull TaskDetailContract.Presenter presenter) {
        mPresenter = checkNotNull(presenter);
    }





尊重作者,尊重原創,參考文章

http://www.jianshu.com/p/569ab68da482

http://www.jianshu.com/p/2ecfc1f4561d



發佈了228 篇原創文章 · 獲贊 45 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章