首页 Android MVP架构
文章
取消

Android MVP架构

什么是MVP?

MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理。

来自维基百科的模型描述

Model-View-Presenter (MVP) 是用户界面设计模式的一种,被广泛用于便捷自动化单元测试和在呈现逻辑中改良分离关注点(separation of concerns)。

  • Model 定义用户界面所需要被显示的资料模型,一个模型包含着相关的业务逻辑。
  • View 视图为呈现用户界面的终端,用以表现来自 Model 的资料,和用户命令路由再经过 Presenter 对事件处理后的资料。
  • Presenter 包含着组件的事件处理,负责检索 Model 获取资料,和将获取的资料经过格式转换与 View 进行沟通。

MVP图示

Android 实现

代码参考谷歌官方的Demo。To-DoApp的todo-mvp-kotlin分支

1. 定义BaseViewBasePresenter

  • 其中BaseView持有一个presenter成员。实现BasePresenter要实现start()方法。
1
2
3
interface BaseView<T> {
    var presenter: T
}
1
2
3
interface BasePresenter {
    fun start()
}

2.明确功能需求,编写功能级的View和Presenter

以Task详情页为例,用户能执行4种操作,分别是编辑Task、删除Task、改变Task完成状态(已完成、未完成)。根据上面的需求,我们Task详情页的Presenter代码如下。

1
2
3
4
5
6
7
8
9
10
interface Presenter : BasePresenter {
    // 编辑Task
    fun editTask()
    // 删除Task
    fun deleteTask()
    // 完成Task
    fun completeTask()
    // 激活Task
    fun activateTask()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
  1. TaskDetailActivity里,将TaskDetailPresenterTaskDetailFragment(已实现View接口) 绑定在一起,如何绑定见下文2。
    1
    2
    3
    4
    5
    6
    7
    
         override fun onCreate(savedInstanceState: Bundle?) {
             ...
             //取得TaskDetailFragment实例
             val taskDetailFragment = ...
             TaskDetailPresenter(..., taskDetailFragment)
             ...
         }
    
  2. TaskDetailPresenter接收实现了View接口的UI,即TaskDetailFragment,并实现Presenter接口,在构造方法的时候通过调用 taskDetailView.presenter = this 绑定在一起。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
     class TaskDetailPresenter(
             ...
             private val taskDetailView: TaskDetailContract.View
     ) : TaskDetailContract.Presenter {
        
         init {
             taskDetailView.presenter = this
         }
        
         ...
         //实现TaskDetailContract.Presenter的方法
         ...
     }
    
  3. TaskDetailFragment实现View接口,并持有presenter实例和Presenter进行交互。在onResume的时候,调用Presenter的start()方法启动Presenter,开始交互。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
     class TaskDetailFragment : Fragment(), TaskDetailContract.View {
            
         override lateinit var presenter: TaskDetailContract.Presenter
        
         override fun onResume() {
             super.onResume()
             presenter.start()
         }
        
         ...
         //实现TaskDetailContract.View的方法和属性
         ...
     }
    
  4. TaskDetailFragment调用TaskDetailPresenter的方法执行业务逻辑,TaskDetailPresenter调用TaskDetailContract.View的方法,让TaskDetailFragment更新页面UI。
    • 调用presenter.deleteTask()删除Task
      1
      2
      3
      4
      5
      
        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()显示删除成功。
      1
      2
      3
      4
      5
      6
      7
      8
      
        override fun deleteTask() {
            if (taskId.isEmpty()) {
                taskDetailView.showMissingTask()
                return
            }
            tasksRepository.deleteTask(taskId)
            taskDetailView.showTaskDeleted()
        }
      
    • TaskDetailFragment执行最终显示UI的方法。
      1
      2
      3
      4
      5
      6
      7
      8
      
        override fun showMissingTask() {
            detailTitle.text = ""
            detailDescription.text = getString(R.string.no_data)
        }
          
        override fun showTaskDeleted() {
            activity?.finish()
        }
      
本文由作者按照 CC BY 4.0 进行授权
热门标签
文章内容
热门标签