Android中的MVP模式
Posted ZhangJianIsAStark
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android中的MVP模式相关的知识,希望对你有一定的参考价值。
一、MVP的基本概念
传统的android应用开发中,View层承载了太多的责任。
它需要完成界面的更新,复杂动画的渲染等UI相关操作,
还需要处理各种业务逻辑。
由于职责不单一,View层的代码往往显得很庞大。
随着功能的增加,View层代码的维护和升级将变得越来越困难。
为了更好的组织并对代码进行分层设计,
就出现了MVP模式。
MVP的全称是Model、View和Presenter。
从名称可以看出,MVP将整个应用分为三层。
其中:
视图(View)层,包含界面相关的功能,例如Activity、Fragment、View等,
专注于用户的交互,实现界面、动画等交互效果。
View层一般会持有Presenter层的引用,
并将非UI的逻辑操作委托给Presenter。
逻辑控制(Presenter)层,充当中间人的角色,用来隔离View和Model层。
它主要负责View层和Model层的控制和交互。
模型(Model)层,主要用于封装各种数据来源。
二、MVP与MVC的区别
MVP是MVC的延伸和改进,MVC的关系如下所示。
与MVP的关系图比较,容易看出,MVC和MVP最大的差异是:MVC中Model和View可以直接通信。
这其实就是造成Activity、Fragment等组件职责不够单一的原因。
MVP中的View层和Model层并没有直接通信,
而是通过中间人Presenter来间接通信,
Presenter和View以及Model的交互都是通过接口来进行的,
因此在符合接口规范的情况下,可以替换Presenter的实现。
三、MVP的开源实现
单纯依靠文字来描述MVP的思想比较单薄,
我们不妨来看看Google提供的示例代码TO-MVP 。
该工程中Activity的主要工作类似于:
@Override
protected void onCreate(Bundle savedInstanceState)
......
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
// 注意到Fragment被传入到Presenter的构造函数中,相当于绑定了
mTasksPresenter = new TasksPresenter(
Injection.provideTasksRepository(getApplicationContext()), tasksFragment);
............
从上述代码可以看出,Activity负责创建Fragment和Presenter。
我们再来看看TaskFragment的代码:
//实现View定义的接口
public class TasksFragment extends Fragment implements TasksContract.View
//Presenter的类型也是个接口
private TasksContract.Presenter mPresenter;
.......
//关联Fragment和Presenter
@Override
public void setPresenter(@NonNull TasksContract.Presenter presenter)
mPresenter = checkNotNull(presenter);
.......
//容易看出,Fragment管理UI相关的工作
//具体的逻辑全部交由Presenter
@Override
public void showFilteringPopUpMenu()
PopupMenu popup = new PopupMenu(getContext(),
getActivity().findViewById(R.id.menu_filter));
popup.getMenuInflater().inflate(R.menu.filter_tasks, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener()
public boolean onMenuItemClick(MenuItem item)
switch (item.getItemId())
case R.id.active:
//实际逻辑给Presenter
mPresenter.setFiltering(TasksFilterType.ACTIVE_TASKS);
break;
case R.id.completed:
mPresenter.setFiltering(TasksFilterType.COMPLETED_TASKS);
break;
default:
mPresenter.setFiltering(TasksFilterType.ALL_TASKS);
break;
mPresenter.loadTasks(false);
return true;
);
popup.show();
............
接下来看看TasksPresenter的代码:
public class TasksPresenter implements TasksContract.Presenter
............
//保留的View也是接口类型
private final TasksContract.View mTasksView;
...........
//从上文的代码,我们知道tasksView实际上就是Fragment
public TasksPresenter(@NonNull TasksRepository tasksRepository,
@NonNull TasksContract.View tasksView)
mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
//Presenter持有View
mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");
//View持有Fragment
mTasksView.setPresenter(this);
//Presenter完成实际的逻辑,与Model交互
@Override
public void start()
loadTasks(false);
//结果交由View来显示
@Override
public void result(int requestCode, int resultCode)
// If a task was successfully added, show snackbar
if (AddEditTaskActivity.REQUEST_ADD_TASK == requestCode
&& Activity.RESULT_OK == resultCode)
mTasksView.showSuccessfullySavedMessage();
.................
最后来看看TasksContract中定义的接口:
//TaskContract内统一约定了View和Presenter的接口
public interface TasksContract
//View的接口主要与展示有关
interface View extends BaseView<Presenter>
void setLoadingIndicator(boolean active);
void showTasks(List<Task> tasks);
....................
//Presenter接口主要与功能逻辑有关
interface Presenter extends BasePresenter
void result(int requestCode, int resultCode);
void loadTasks(boolean forceUpdate);
void addNewTask();
.........
我们来看看Google自己提供的MVP架构图:
四、总结
MVP实际上没有任何神秘可言,从设计的角度来看,
实际上就是为了保持类的功能单一,并且面向接口编程。
以上是关于Android中的MVP模式的主要内容,如果未能解决你的问题,请参考以下文章