什么是MVP?
MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理。
来自维基百科的模型描述
Model-View-Presenter (MVP) 是用户界面设计模式的一种,被广泛用于便捷自动化单元测试和在呈现逻辑中改良分离关注点(separation of concerns)。
- Model 定义用户界面所需要被显示的资料模型,一个模型包含着相关的业务逻辑。
- View 视图为呈现用户界面的终端,用以表现来自 Model 的资料,和用户命令路由再经过 Presenter 对事件处理后的资料。
- Presenter 包含着组件的事件处理,负责检索 Model 获取资料,和将获取的资料经过格式转换与 View 进行沟通。

Android 实现
代码参考谷歌官方的Demo。To-DoApp的todo-mvp-kotlin分支
1. 定义BaseView和BasePresenter
- 其中
BaseView持有一个presenter成员。实现BasePresenter要实现start()方法。
interface BaseView<T> {
var presenter: T
}
interface BasePresenter {
fun start()
}
2.明确功能需求,编写功能级的View和Presenter
以Task详情页为例,用户能执行4种操作,分别是编辑Task、删除Task、改变Task完成状态(已完成、未完成)。根据上面的需求,我们Task详情页的Presenter代码如下。
interface Presenter : BasePresenter {
// 编辑Task
fun editTask()
// 删除Task
fun deleteTask()
// 完成Task
fun completeTask()
// 激活Task
fun activateTask()
}
interface View : BaseView<Presenter> {
val isActive: Boolean
// 是否显示加载中
fun setLoadingIndicator(active: Boolean)
// 显示找不到Task
fun showMissingTask()
// Task为空时,隐藏标题
fun hideTitle()
// 显示并显示标题
fun showTitle(title: String)
// Task为空时,隐藏描述
fun hideDescription()
// 显示并显示描述
fun showDescription(description: String)
// 显示Task的完成状态
fun showCompletionStatus(complete: Boolean)
// 跳转编辑Task的Activity
fun showEditTask(taskId: String)
// 执行Task删除后的逻辑
fun showTaskDeleted()
// 显示Task已完成的界面
fun showTaskMarkedComplete()
// 显示Task已已激活的界面
fun showTaskMarkedActive()
}
3.业务代码分析
TaskDetailActivity是容器,具体实现逻辑在TaskDetailFragment。
在
TaskDetailActivity里,将TaskDetailPresenter和TaskDetailFragment(已实现View接口) 绑定在一起,如何绑定见下文2。override fun onCreate(savedInstanceState: Bundle?) { ... //取得TaskDetailFragment实例 val taskDetailFragment = ... TaskDetailPresenter(..., taskDetailFragment) ... }TaskDetailPresenter接收实现了View接口的UI,即TaskDetailFragment,并实现Presenter接口,在构造方法的时候通过调用taskDetailView.presenter = this绑定在一起。class TaskDetailPresenter( ... private val taskDetailView: TaskDetailContract.View ) : TaskDetailContract.Presenter { init { taskDetailView.presenter = this } ... //实现TaskDetailContract.Presenter的方法 ... }TaskDetailFragment实现View接口,并持有presenter实例和Presenter进行交互。在onResume的时候,调用Presenter的start()方法启动Presenter,开始交互。class TaskDetailFragment : Fragment(), TaskDetailContract.View { override lateinit var presenter: TaskDetailContract.Presenter override fun onResume() { super.onResume() presenter.start() } ... //实现TaskDetailContract.View的方法和属性 ... }TaskDetailFragment调用TaskDetailPresenter的方法执行业务逻辑,TaskDetailPresenter调用TaskDetailContract.View的方法,让TaskDetailFragment更新页面UI。- 调用
presenter.deleteTask()删除Task
override fun onOptionsItemSelected(item: MenuItem): Boolean { val deletePressed = item.itemId == R.id.menu_delete if (deletePressed) presenter.deleteTask() return deletePressed }- presenter根据实际情况调用
View的方法更新UI。如果taskId为空,则调用showMissingTask()显示没有Task,否则执行删除逻辑并调用showTaskDeleted()显示删除成功。
override fun deleteTask() { if (taskId.isEmpty()) { taskDetailView.showMissingTask() return } tasksRepository.deleteTask(taskId) taskDetailView.showTaskDeleted() }TaskDetailFragment执行最终显示UI的方法。
override fun showMissingTask() { detailTitle.text = "" detailDescription.text = getString(R.string.no_data) } override fun showTaskDeleted() { activity?.finish() }- 调用