一、MVC
1.什么是MVC
M
可以由数据类(结合数据文件)实现;
C
即控制/调度逻辑
、业务逻辑
【业务功能实现】,由Activity
实现;
V
则xml布局文件
与UI逻辑
【UI逻辑由Activity
实现】;
目前很多企业都采用敏捷开发的开发方式,在的用户界面逻辑的变更频率往往高于业务逻辑。 如果将表示界面代码和业务逻辑组合在单个对象中,则每次更改用户界面时都必须修改包含业务逻辑的对象, 这常常会引发错误,并且需要在每次进行细微的用户界面更改后重新测试业务逻辑。
将代码实现分为三部分,将容易变化和不易变化的部分分离,实现分离关注点,方便后续代码维护和软件迭代。
2.如何实现MVC
(1)Model
package com.example.todoproject
data class TodoItem(
var id: Int,
var title: String,
var description: String,
var isCompleted: Boolean
)
package com.example.todoproject
class TodoDao(todoListActivity: TodoListActivity) {
private val todos = mutableListOf<TodoItem>()
init {
// 初始化一些模拟数据
todos.add(TodoItem(1, "Task 1", "Description of Task 1", false))
todos.add(TodoItem(2, "Task 2", "Description of Task 2", false))
todos.add(TodoItem(3, "Task 3", "Description of Task 3", false))
}
fun insertTodo(todo: TodoItem): Long {
todo.id = todos.size + 1
todos.add(todo)
return todo.id.toLong()
}
fun getAllTodos(): List<TodoItem> {
return todos
}
fun updateTodo(todo: TodoItem) {
val index = todos.indexOfFirst { it.id == todo.id }
if (index!= -1) {
todos[index] = todo
}
}
}
(2)View和Controller
package com.example.todoproject
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
class TodoListActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var editTextTitle: EditText
private lateinit var editTextDescription: EditText
private lateinit var buttonAddTodo: Button
private lateinit var listViewTodos: ListView
private lateinit var todoAdapter: TodoAdapter
private lateinit var todoDao: TodoDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_todo_list)
editTextTitle = findViewById(R.id.editTextTitle)
editTextDescription = findViewById(R.id.editTextDescription)
buttonAddTodo = findViewById(R.id.buttonAddTodo)
listViewTodos = findViewById(R.id.listViewTodos)
buttonAddTodo.setOnClickListener(this)
todoDao = TodoDao(this)
val todos = todoDao.getAllTodos()
todoAdapter = TodoAdapter(this, todos)
listViewTodos.adapter = todoAdapter
}
override fun onClick(v: View) {
if (v.id == R.id.buttonAddTodo) {
val title = editTextTitle.text.toString()
val description = editTextDescription.text.toString()
val todo = TodoItem(0, title, description, false)
val id = todoDao.insertTodo(todo)
todo.id = id.toInt()
todoAdapter.addTodo(todo)
editTextTitle.text.clear()
editTextDescription.text.clear()
}
}
override fun onDestroy() {
super.onDestroy()
}
}
package com.example.todoproject
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.TextView
import java.util.*
class TodoAdapter(context: Context, todos: List<TodoItem>) : ArrayAdapter<TodoItem>(context, 0, todos) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false)
}
val textView = view!!.findViewById<TextView>(android.R.id.text1)
val todo = getItem(position)
textView.text = todo?.title
return view
}
fun addTodo(todo: TodoItem) {
add(todo)
notifyDataSetChanged()
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/editTextTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/editTextDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/buttonAddTodo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Todo" />
<ListView
android:id="@+id/listViewTodos"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
3.MVC的优缺点
优点:简单粗暴,适合小项目
缺点:View和Controller之间职责不清晰:我们会发现,View和Controller均依赖于Model。 但是,Model既不依赖于View,也不依赖于Controller,尤其在Android中,View和Controller都在Activity中实现,导致View和Controller的逻辑并不清晰,导致职责分离不彻底,使我们最初使用MVC的目的并没有实现
二、MVP
1.什么是MVP
- M(model)代表的是将会显示在view(UI)中的数据。
- V(view)是显示数据(model)和UI逻辑。
- P(presenter)扮演的是“中间人”的作用(就如MVC中的controller),且presenter同时引用view和model。作为 View 和 Model 之间的中介,负责处理用户输入和更新 View。Presenter 接收来自 View 的用户输入,调用 Model 中的方法进行数据处理,并将结果返回给 View 进行显示。
MVC 和 MVP 的区别就是,在 MVP 中 M 和 V 没有直接通信,从而实现了三者的解耦合
2.如何实现MVP
1.View
import com.example.todoproject.TodoItem
interface TodoView {
fun showTodos(todos: List<TodoItem>)
fun showError(message: String)
}
package com.example.todoprojectmvp
import TodoAdapter
import TodoPresenter
import TodoPresenterImpl
import TodoView
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import android.widget.Toast
import com.example.todoproject.TodoDao
import com.example.todoproject.TodoItem
class TodoListActivity : AppCompatActivity() , TodoView, View.OnClickListener {
private lateinit var editTextTitle: EditText
private lateinit var editTextDescription: EditText
private lateinit var buttonAddTodo: Button
private lateinit var listViewTodos: ListView
private lateinit var presenter: TodoPresenter
private lateinit var todoAdapter: TodoAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_todo_list)
editTextTitle = findViewById(R.id.editTextTitle)
editTextDescription = findViewById(R.id.editTextDescription)
buttonAddTodo = findViewById(R.id.buttonAddTodo)
listViewTodos = findViewById(R.id.listViewTodos)
buttonAddTodo.setOnClickListener(this)
presenter = TodoPresenterImpl(this)
// 初始化适配器
todoAdapter = TodoAdapter(this, emptyList())
listViewTodos.adapter = todoAdapter
}
override fun onResume() {
super.onResume()
presenter.loadTodos()
}
override fun showTodos(todos: List<TodoItem>) {
// 更新列表视图
todoAdapter.todos = todos
todoAdapter.notifyDataSetChanged()
}
override fun showError(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
override fun onClick(v: View?) {
if (v != null) {
if (v.id == R.id.buttonAddTodo) {
val title = editTextTitle.text.toString()
val description = editTextDescription.text.toString()
presenter.addTodo(title, description)
editTextTitle.text.clear()
editTextDescription.text.clear()
}
}
}
}
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import com.example.todoproject.TodoItem
import com.example.todoprojectmvp.R
class TodoAdapter(private val context: Context, var todos: List<TodoItem>) : BaseAdapter() {
override fun getCount(): Int {
return todos.size
}
override fun getItem(position: Int): TodoItem {
return todos[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false)
}
val textView = view!!.findViewById<TextView>(android.R.id.text1)
val todo = getItem(position)
textView.text = todo.title
return view
}
}
2.Presenter
interface TodoPresenter {
fun loadTodos()
fun addTodo(title: String, description: String)
}
import com.example.todoproject.TodoDao
import com.example.todoproject.TodoItem
import com.example.todoprojectmvp.TodoListActivity
class TodoPresenterImpl(private val view: TodoView) : TodoPresenter {
private lateinit var todoDao: TodoDao
init {
todoDao = TodoDao(view as TodoListActivity)
}
override fun loadTodos() {
val todos = todoDao.getAllTodos()
view.showTodos(todos)
}
override fun addTodo(title: String, description: String) {
val todo = TodoItem(0, title, description, false)
val id = todoDao.insertTodo(todo)
todo.id = id.toInt()
loadTodos()
}
}
3.Model
package com.example.todoproject
data class TodoItem(
var id: Int,
var title: String,
var description: String,
var isCompleted: Boolean
)
package com.example.todoproject
import com.example.todoprojectmvp.TodoListActivity
class TodoDao(todoListActivity: TodoListActivity) {
private val todos = mutableListOf<TodoItem>()
init {
// 初始化一些模拟数据
todos.add(TodoItem(1, "Task 1", "Description of Task 1", false))
todos.add(TodoItem(2, "Task 2", "Description of Task 2", false))
todos.add(TodoItem(3, "Task 3", "Description of Task 3", false))
}
fun insertTodo(todo: TodoItem): Long {
todo.id = todos.size + 1
todos.add(todo)
return todo.id.toLong()
}
fun getAllTodos(): List<TodoItem> {
return todos
}
fun updateTodo(todo: TodoItem) {
val index = todos.indexOfFirst { it.id == todo.id }
if (index!= -1) {
todos[index] = todo
}
}
}
3.MVP的优缺点
优点:实现分离,实现了三种职责之间的解耦
缺点:P可能会出现代码过于繁杂的情况:View的改变和Model的改变都需要P进行逻辑处理,例如在Todo的例子中,当用户点击AddTODO时,p从View获取数据,并需要代码手动添加到Model中,同时,需要代码手动更新View中的TodoList,导致P中代码的冗杂。
一、什么是MVVM?
MVVM 即 Model-View-ViewModel,是一种用于构建用户界面的软件架构模式。它的主要目的是将用户界面的开发与业务逻辑的开发分离开来,提高代码的可维护性、可测试性和可扩展性。
Model 代表数据模型,负责存储和管理应用程序的数据。
View 是用户界面,负责展示数据和接收用户输入。
ViewModel 则是连接 Model 和 View 的桥梁,它将 Model 中的数据转换为 View 可以显示的形式,并处理 View 中的用户输入,将其转换为对 Model 的操作。
二、为什么使用MVVM架构?
View和Model进行双向绑定(data-binding), 两者之间有一方发生变化则会反应到另一方上;
1.优点:
1.清晰的结构划分
2.快速响应变化:由于 View 和 Model 之间通过 ViewModel 进行解耦,当需求变化时,可以只修改相应的部分,而不会影响到其他部分
2.缺点:
1.学习成本(略)高
2.性能问题:例如,数据频繁变化,界面频繁变化
3.代码复杂,调试困难
三、MVVM架构如何实现的?
1.类图
2.示例代码
(1)Model
public class TodoItem {
private int id;
private String title;
private boolean completed;
public TodoItem(int id, String title, boolean completed) {
this.id = id;
this.title = title;
this.completed = completed;
}
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
}
(2)ViewModel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import com.example.todoproject.TodoItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class TodoViewModel(private val todoAdapter: TodoAdapter, application: Application) : AndroidViewModel(application) {
private val repository: TodoRepository
var todoItems: LiveData<List<TodoItem>>
init {
repository = TodoRepository(application)
todoItems = repository.getTodoItems()
}
fun addTodo(todoItem: TodoItem) {
repository.insertTodo(todoItem)
todoItems = repository.getTodoItems()
updateTodo(todoItem)
}
fun updateTodo(todoItem: TodoItem) {
CoroutineScope(Dispatchers.IO).launch {
repository.updateTodo(todoItem)
withContext(Dispatchers.Main) {
todoAdapter.notifyDataSetChanged()
}
}
}
}
(3)View
package com.example.todoprojectmvvm
import TodoAdapter
import TodoViewModel
import android.content.ContentValues.TAG
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.todoproject.TodoItem
class TodoListActivity : AppCompatActivity() {
private lateinit var editTextTitle: EditText
private lateinit var editTextDescription: EditText
private lateinit var buttonAddTodo: Button
private lateinit var todoViewModel: TodoViewModel
private lateinit var todoAdapter: TodoAdapter
private lateinit var listViewTodos: ListView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_todo_list)
editTextTitle = findViewById(R.id.editTextTitle)
editTextDescription = findViewById(R.id.editTextDescription)
buttonAddTodo = findViewById(R.id.buttonAddTodo)
listViewTodos = findViewById(R.id.listViewTodos)
// 创建 ViewModel 并传递 Adapter
todoAdapter = TodoAdapter(this, emptyList())
todoViewModel = TodoViewModel( todoAdapter, application)
listViewTodos.adapter = todoAdapter
todoViewModel.todoItems.observe(this, Observer { todoItems ->
todoAdapter.updateData(todoItems)
})
buttonAddTodo.setOnClickListener {
val title = editTextTitle.text.toString()
val description = editTextDescription.text.toString()
val todoItem = TodoItem(0, title, description, false)
todoViewModel.addTodo(todoItem)
editTextTitle.text.clear()
editTextDescription.text.clear()
}
}
}
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import com.example.todoproject.TodoItem
class TodoAdapter(private val context: Context, var todos: List<TodoItem>) : BaseAdapter() {
override fun getCount(): Int {
return todos.size
}
override fun getItem(position: Int): TodoItem {
return todos[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false)
}
val textView = view!!.findViewById<TextView>(android.R.id.text1)
val todo = getItem(position)
textView.text = todo.title
return view
}
fun updateData(newTodos: List<TodoItem>) {
todos = newTodos
notifyDataSetChanged()
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/editTextTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/editTextDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/buttonAddTodo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Todo" />
<ListView
android:id="@+id/listViewTodos"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
致此,MVC、MVP和MVVM讲解结束,有任何疑问,欢迎提问
标签:MVP,MVVM,MVC,fun,import,android,id,todos,View From: https://blog.csdn.net/m0_60892159/article/details/143468326