zoukankan      html  css  js  c++  java
  • MVP学习笔记——参考Google官方demo

    demo地址:https://github.com/googlesamples/android-architecture

    在这个项目里,每个包的分工都很明确,大体上来说,一个包会对应一个界面。一个界面就会对应一个MVP。

    M:还是模型层和业务层

    V:视图层。Activity或者Fragment,在这份代码里面,Google是把Fragment当作一个V,而不是Activity

    P:Prensenter,用来控制V。

    按我的理解是,MVP主要就是通过P来解耦M和V,P用来沟通M和V,使得两者不必直接对话,V可以安心的负责显示,与用户的交互,以及数据的操作工作都交给P来完成。这样毫无疑问,java文件会变多,但是整个的代码结构、思路会更加清晰,更容易打理和维护。

    M:定义了一个接口TasksDataSource.java,从接口可以看出,主要也就是一些数据的操作,跟以前的MVC区别不大。这个没啥好说的。

    public interface TasksDataSource {
    
        interface LoadTasksCallback {
    
            void onTasksLoaded(List<Task> tasks);
    
            void onDataNotAvailable();
        }
    
        interface GetTaskCallback {
    
            void onTaskLoaded(Task task);
    
            void onDataNotAvailable();
        }
    
        void getTasks(@NonNull LoadTasksCallback callback);
    
        void getTask(@NonNull String taskId, @NonNull GetTaskCallback callback);
    
        void saveTask(@NonNull Task task);
    
        void completeTask(@NonNull Task task);
    
        void completeTask(@NonNull String taskId);
    
        void activateTask(@NonNull Task task);
    
        void activateTask(@NonNull String taskId);
    
        void clearCompletedTasks();
    
        void refreshTasks();
    
        void deleteAllTasks();
    
        void deleteTask(@NonNull String taskId);
    }

    这里将V和P的接口都放在一个***Contract.java中,这样便于管理,切一目了然。

    /**
     * This specifies the contract between the view and the presenter.
     */
    public interface TasksContract {
    
        interface View extends BaseView<Presenter> {
    
            void setLoadingIndicator(boolean active);
    
            void showTasks(List<Task> tasks);
    
            void showAddTask();
    
            void showTaskDetailsUi(String taskId);
    
            void showTaskMarkedComplete();
    
            void showTaskMarkedActive();
    
            void showCompletedTasksCleared();
    
            void showLoadingTasksError();
    
            void showNoTasks();
    
            void showActiveFilterLabel();
    
            void showCompletedFilterLabel();
    
            void showAllFilterLabel();
    
            void showNoActiveTasks();
    
            void showNoCompletedTasks();
    
            void showSuccessfullySavedMessage();
    
            boolean isActive();
    
            void showFilteringPopUpMenu();
        }
    
        interface Presenter extends BasePresenter {
    
            void result(int requestCode, int resultCode);
    
            void loadTasks(boolean forceUpdate);
    
            void addNewTask();
    
            void openTaskDetails(@NonNull Task requestedTask);
    
            void completeTask(@NonNull Task completedTask);
    
            void activateTask(@NonNull Task activeTask);
    
            void clearCompletedTasks();
    
            void setFiltering(TasksFilterType requestType);
    
            TasksFilterType getFiltering();
        }
    }
    //BaseView.java
    public interface BaseView<T> {
    
        void setPresenter(T presenter);
    
    }
    
    //BasePresenter.java
    public interface BasePresenter {
    
        void start();
    
    }

    V:前面说到Google将Fragment看作一个V而不是Activity,所以这里用Fragment来实现V接口。

    public class TasksFragment extends Fragment implements TasksContract.View {
    
        public TasksFragment() {
            // Requires empty public constructor
        }
    
        public static TasksFragment newInstance() {
            return new TasksFragment();
        }
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mListAdapter = new TasksAdapter(new ArrayList<Task>(0), mItemListener);
        }
    
        @Override
        public void onResume() {
            super.onResume();
            mPresenter.start();
        }
    
        @Override
        public void setPresenter(@NonNull TasksContract.Presenter presenter) {
            mPresenter = checkNotNull(presenter);
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            mPresenter.result(requestCode, resultCode);
        }
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View root = inflater.inflate(R.layout.tasks_frag, container, false);
    
            // Set up tasks view
            // 也就是通常的findView等一些View的初始化常规操作
            ListView listView = (ListView) root.findViewById(R.id.tasks_list);
            listView.setAdapter(mListAdapter);
            …………
            …………
            return root;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.menu_clear:
                    mPresenter.clearCompletedTasks();
                    break;
                case R.id.menu_filter:
                    showFilteringPopUpMenu();
                    break;
                case R.id.menu_refresh:
                    mPresenter.loadTasks(true);
                    break;
            }
            return true;
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.tasks_fragment_menu, menu);
        }
    
    
        /**
         * Listener for clicks on tasks in the ListView.
         */
        TaskItemListener mItemListener = new TaskItemListener() {
            @Override
            public void onTaskClick(Task clickedTask) {
                mPresenter.openTaskDetails(clickedTask);
            }
    
            @Override
            public void onCompleteTaskClick(Task completedTask) {
                mPresenter.completeTask(completedTask);
            }
    
            @Override
            public void onActivateTaskClick(Task activatedTask) {
                mPresenter.activateTask(activatedTask);
            }
        };
    
        private static class TasksAdapter extends BaseAdapter {
                //adapter
        }
    
        public interface TaskItemListener {
    
            void onTaskClick(Task clickedTask);
    
            void onCompleteTaskClick(Task completedTask);
    
            void onActivateTaskClick(Task activatedTask);
        }
    
    }

    可以看到,所有的交互操作,像点击一个task,标记完成task等,V并不处理,而是转交给P去处理,也就是这样,便将控制的权利交到了P手中。

    P:那么P是如何扮演一个沟通者和控制者角色的呢?从代码中可以看到,P手握M和V两者的引用,这样便可以轻松的做好他的工作了:操作数据,控制显示,处理与用户交互。

    public class TaskDetailPresenter implements TaskDetailContract.Presenter {
    
        private final TasksRepository mTasksRepository;
    
        private final TaskDetailContract.View mTaskDetailView;
    
        @Nullable
        private String mTaskId;
    
        public TaskDetailPresenter(@Nullable String taskId,
                                   @NonNull TasksRepository tasksRepository,
                                   @NonNull TaskDetailContract.View taskDetailView) {
            this.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() {
            if (null == mTaskId || mTaskId.isEmpty()) {
                mTaskDetailView.showMissingTask();
                return;
            }
    
            mTaskDetailView.setLoadingIndicator(true);
            mTasksRepository.getTask(mTaskId, new TasksDataSource.GetTaskCallback() {
                @Override
                public void onTaskLoaded(Task task) {
                    // The view may not be able to handle UI updates anymore
                    if (!mTaskDetailView.isActive()) {
                        return;
                    }
                    mTaskDetailView.setLoadingIndicator(false);
                    if (null == task) {
                        mTaskDetailView.showMissingTask();
                    } else {
                        showTask(task);
                    }
                }
    
                @Override
                public void onDataNotAvailable() {
                    // The view may not be able to handle UI updates anymore
                    if (!mTaskDetailView.isActive()) {
                        return;
                    }
                    mTaskDetailView.showMissingTask();
                }
            });
        }
    
        @Override
        public void editTask() {
            if (null == mTaskId || mTaskId.isEmpty()) {
                mTaskDetailView.showMissingTask();
                return;
            }
            mTaskDetailView.showEditTask(mTaskId);
        }
    
        @Override
        public void deleteTask() {
            mTasksRepository.deleteTask(mTaskId);
            mTaskDetailView.showTaskDeleted();
        }
    
        @Override
        public void completeTask() {
            if (null == mTaskId || mTaskId.isEmpty()) {
                mTaskDetailView.showMissingTask();
                return;
            }
            mTasksRepository.completeTask(mTaskId);
            mTaskDetailView.showTaskMarkedComplete();
        }
    
        @Override
        public void activateTask() {
            if (null == mTaskId || mTaskId.isEmpty()) {
                mTaskDetailView.showMissingTask();
                return;
            }
            mTasksRepository.activateTask(mTaskId);
            mTaskDetailView.showTaskMarkedActive();
        }
    
        private void showTask(Task task) {
            String title = task.getTitle();
            String description = task.getDescription();
    
            if (title != null && title.isEmpty()) {
                mTaskDetailView.hideTitle();
            } else {
                mTaskDetailView.showTitle(title);
            }
    
            if (description != null && description.isEmpty()) {
                mTaskDetailView.hideDescription();
            } else {
                mTaskDetailView.showDescription(description);
            }
            mTaskDetailView.showCompletionStatus(task.isCompleted());
        }
    }

    我发现像之前那本《Android编程权威指南》还有Google官方这个例子,对Fragment都情有独钟,都在鼓励使用Fragment而不是Activity,所以Fragment理所当然的成为了V。那么在MVP中Activity干嘛呢?

    public class TasksActivity extends AppCompatActivity {
    
        private static final String CURRENT_FILTERING_KEY = "CURRENT_FILTERING_KEY";
    
        private DrawerLayout mDrawerLayout;
    
        private TasksPresenter mTasksPresenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.tasks_act);
    
            // Set up the toolbar.
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            ActionBar ab = getSupportActionBar();
            ab.setHomeAsUpIndicator(R.drawable.ic_menu);
            ab.setDisplayHomeAsUpEnabled(true);
    
            // Set up the navigation drawer.
            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
            mDrawerLayout.setStatusBarBackground(R.color.colorPrimaryDark);
            NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
            if (navigationView != null) {
                setupDrawerContent(navigationView);
            }
    
            TasksFragment tasksFragment =
                    (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
            if (tasksFragment == null) {
                // Create the fragment
                tasksFragment = TasksFragment.newInstance();
                ActivityUtils.addFragmentToActivity(
                        getSupportFragmentManager(), tasksFragment, R.id.contentFrame);
            }
    
            // Create the presenter
            mTasksPresenter = new TasksPresenter(
                    Injection.provideTasksRepository(getApplicationContext()), tasksFragment);
    
            // Load previously saved state, if available.
            if (savedInstanceState != null) {
                TasksFilterType currentFiltering =
                        (TasksFilterType) savedInstanceState.getSerializable(CURRENT_FILTERING_KEY);
                mTasksPresenter.setFiltering(currentFiltering);
            }
        }
    }

    Activity主要用来创建Fragment、初始化P(也就是关联V和P)

    在BaseView中有个setPresenter()方法,而通常在P的构造函数中得到V的实例后会调用该方法来实现V和P的绑定。

    public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {
            mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
            mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");
    
            mTasksView.setPresenter(this);
        }

    在V通过setPresenter得到P后,便在onResume()中调用BasePresenter的start()方法来初始化P,其实也就是初始化UI界面,毕竟P掌管了V的控制权。

     @Override
        public void onResume() {
            super.onResume();
            mPresenter.start();
        }
  • 相关阅读:
    centos7下磁盘空间调整
    centos7下 查看CPU、内存、磁盘的使用情况
    centos7中Spark集群的安装与配置(Hadoop2.6.5+spark2.3.3)
    linux下mysql ---- Host '' is not allowed to connect to this MySQL server
    11-1、多线程
    10-2、对象的序列化和反序列化
    9-1、注解
    8-1、泛型
    7-1、集合
    6-1、异常处理
  • 原文地址:https://www.cnblogs.com/i-love-kobe/p/5578106.html
Copyright © 2011-2022 走看看