Google官方MVP脑补

Posted 劲火星空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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



与50位技术专家面对面 20年技术见证,附赠技术全景图

以上是关于Google官方MVP脑补的主要内容,如果未能解决你的问题,请参考以下文章

Google官方MVP模式示例项目解析 todo-mvp

一张图看Google MVP设计架构

从Google的todo-mvp源码中学习MVP模式

从Google的todo-mvp源码中学习MVP模式

如何更高效的使用MVP以及官方MVP架构解析

MVP架构-Android官方MVP项目和响应式MVP-RxJava项目架构分析对比解读