【android-architecture】todo-mvp
来源:互联网 发布:暗黑破坏神3数据库app 编辑:程序博客网 时间:2024/05/18 14:27
MVP简介
MVP 对应一个应用分成三个基础的部分
Model层 负责处理应用的数据部分
View层 负责应用的界面绘制和用户交互
Presenter计算层 负责连接View和Model,也负责操控View
MVP 的一些基础规则
- View只负责根据Presenter的计算结果展示对应的界面
- View将用户的动作反馈给Presenter
- View永远不与Model交互
- Presenter负责解析View的请求并计算后通知View显示
- Model负责从本地或者网络拉取数据
todo-mvp
这个例子中每个界面由以下四个部分实现
1. Contract 定义View和Presenter之间的联系,其实是定义所有View和Presenter的相关操作的接口
2. Activity 创建Presenter和Fragment
3. Fragment mvp中的view层,实现了Contract中的View接口,负责界面的展示
4. Presenter 实现Contract中对应的Presenter接口
代码实现
首先看看两个View和Presenter的两个基类BaseView
和BaseView
,都只有一个方法,所有的View都实现BaseView,通过setPresenter可以让View持有Presenter,Presenter都实现BasePresenter,在start方法中调用初始化数据的操作。
public interface BaseView<T> { void setPresenter(T presenter);}public interface BasePresenter { void start();}
demo是一个简单的备忘录,每个文件夹是一个界面,这个demo中有四个界面,添加和编辑界面,统计界面,任务详情,任务列表,以任务详情页为例
可以看到界面上的功能有 编辑,删除,完成(CheckBox选中),任务置为活跃(CheckBox取消选中),可以抽象出对应的Presenter四个方法,见TaskDetailContract.Presenter
根据task展示的各种状态View抽象出的接口见TaskDetailContract.View
,在fragment的resume方法中调用present的start方法,委托presenter开始准备数据,presenter受到委托后调用model层的方法获取数据,并调用View的setLoadingIndicator方法将View置成加载中的状态,等数据加载完成后根据是否有数据决定调用view的显示数据方法还是空页面方法,这样就实现了之前所说的view只绘制相应界面,presenter决定显示什么界面,model只负责获取数据,但时presenter决定什么时候获取,用户其他的操作也是和加载数据一样按照上述的流程
/** * This specifies the contract between the view and the 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(); }}
在activity中分别初始化View和Presenter
TaskDetailActivity.java protected void onCreate(Bundle savedInstanceState) { String taskId = getIntent().getStringExtra(EXTRA_TASK_ID); //初始化View TaskDetailFragment taskDetailFragment = (TaskDetailFragment) getSupportFragmentManager() .findFragmentById(R.id.contentFrame); if (taskDetailFragment == null) { taskDetailFragment = TaskDetailFragment.newInstance(taskId); ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), taskDetailFragment, R.id.contentFrame); } // 初始化 presenter new TaskDetailPresenter( taskId, Injection.provideTasksRepository(getApplicationContext()), taskDetailFragment); } TaskDetailPresenter.java public class TaskDetailPresenter implements TaskDetailContract.Presenter { public TaskDetailPresenter(@Nullable String taskId, @NonNull TasksRepository tasksRepository, @NonNull TaskDetailContract.View taskDetailView) { mTaskId = taskId; //获取数据仓库,也就是Model层的引用 mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null!"); //获取View层的引用 mTaskDetailView = checkNotNull(taskDetailView, "taskDetailView cannot be null!"); //将自己传给View层,这样View就有了presenter的引用 mTaskDetailView.setPresenter(this); } /** *初始化数据 **/ @Override public void start() { openTask(); } private void openTask() { if (Strings.isNullOrEmpty(mTaskId)) { 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 { //数据加载完成后改变View显示状态 showTask(task); } } @Override public void onDataNotAvailable() { // The view may not be able to handle UI updates anymore if (!mTaskDetailView.isActive()) { return; } mTaskDetailView.showMissingTask(); } }); } } TaskDetailPresenter.java public class TaskDetailFragment extends Fragment implements TaskDetailContract.View { //调用presenter的start方法开始加载数据 public void onResume() { super.onResume(); mPresenter.start(); } //保存presenter引用 @Override public void setPresenter(@NonNull TaskDetailContract.Presenter presenter) { mPresenter = checkNotNull(presenter); }}
- 【android-architecture】todo-mvp
- Android-Architecture之todo-mvp
- Google 的android-architecture,todo-mvp解析
- android-architecture学习——todo‑mvp
- 【android-architecture】TODO-DataBinding
- Android todo-mvp
- Android 官方示例:android-architecture 学习笔记(二)之todo-mvp
- Android 官方示例:android-architecture 学习笔记(三)之todo-mvp-loaders
- Android 官方示例:android-architecture 学习笔记(五)之todo-mvp-clean
- Android 官方示例:android-architecture 学习笔记(六)之todo-mvp-contentproviders
- mvp part1 android-mvp-architecture
- MVP Architecture on Android
- Android MVP架构,android-architecture
- Android Architecture Components+MVP 实战
- Android Todo MVP 框架分析和例子
- MVP android-architecture README解析(一)
- 学习Android Architecture Blueprints(一)-mvp分支
- TODO-MVP源码解析
- ARM的相关知识
- SEO的瞬间决动影响力因素
- Java桥接模式
- 程序员创业会面临什么困境?
- 不同页面cookie删除没反应
- 【android-architecture】todo-mvp
- 自定义环形进度条
- idea svn 无法上传和更新
- Oracle通过PL/SQL工具导出/导入excel表格
- php 设置临时内存和超时设置脚本最大执行时间
- thymeleaf快速入门大概
- plt.imshow(image)不顯示圖片
- ACM (8) 一种排序
- spring中配置<mvc:default-servlet-handler />后必须配置<mvc:annotation-driven/>的问题