首先看下我们的页面
一个edittext,一个获取用户信息的button,一个展示用户信息的textview
实现:点击按钮,根据用户输入的账号,获取账号信息并显示在textview上
现在我们用三种方式实现
(1)不使用任何模式
(2)mvc模式
(3)mvp模式
前提:我们定义bean类和callback类
Account.class
package com.jyr.kotlindemo.designPatterns
//账号信息
class Account {
//账号名称
var accountName: String = ""
//账号等级
var level: Int = 1
}
CallBack.class
package com.jyr.kotlindemo.designPatterns
interface CallBack {
fun onSuccess(account: Account)
fun onFail()
}
1. 不使用任何模式下,页面效果如下
ModelActivity.class
package com.jyr.kotlindemo.designPatterns
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.jyr.kotlindemo.R
import com.jyr.kotlindemo.designPatterns.mvc.MVCActivity
import com.jyr.kotlindemo.designPatterns.mvp.MVPActivity
import kotlin.random.Random
public class ModelActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var etCountId: EditText
private lateinit var btnGetInfo: Button
private lateinit var tvUserAccountInfo: TextView
private lateinit var btnMvcMode: Button
private lateinit var btnMvpModel: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_model)
//初始化控件
etCountId = findViewById<EditText>(R.id.et_account_id)
btnGetInfo = findViewById<Button>(R.id.btn_get_info)
tvUserAccountInfo = findViewById<TextView>(R.id.tv_user_account_info)
btnMvcMode = findViewById<Button>(R.id.btn_mvc_mode)
btnMvpModel = findViewById(R.id.btn_mvp_mode)
btnGetInfo.setOnClickListener(this)
btnMvcMode.setOnClickListener(this)
btnMvpModel.setOnClickListener(this)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.btn_get_info -> {
getAccountData(getUserInputAccount(), object : CallBack {
override fun onSuccess(account: Account) {
showSuccessPage(account)
}
override fun onFail() {
showFailPage()
}
})
}
R.id.btn_mvc_mode -> startActivity(Intent(this, MVCActivity::class.java))
R.id.btn_mvp_mode -> startActivity(Intent(this, MVPActivity::class.java))
}
}
//获取用户输入的信息
fun getUserInputAccount(): String {
return etCountId.text.toString()
}
//展示获取数据成功的界面
fun showSuccessPage(account: Account) {
tvUserAccountInfo.setText("用户名为${account.accountName},用户等级为${account.level}")
}
//展示获取数据失败的界面
fun showFailPage() {
tvUserAccountInfo.setText("获取用户信息失败")
}
//请求接口:获取账户的数据(次数模拟网络请求)
fun getAccountData(accountName: String, callBack: CallBack) {
//随机一个boolean
val random = Random
val nextBoolean = random.nextBoolean()
if (nextBoolean) {
//成功的话,返回用户信息
val account = Account()
account.accountName = accountName
account.level = 100
callBack.onSuccess(account)
} else {
callBack.onFail()
}
}
}
activity_model.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/dp_20"
tools:context=".designPatterns.ModelActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/sp_18"
android:text="不使用任何模式下" />
<EditText
android:id="@+id/et_account_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入账号"
android:maxLines="1" />
<Button
android:id="@+id/btn_get_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:text="获取用户信息" />
<TextView
android:id="@+id/tv_user_account_info"
android:text="用户信息:"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_20" />
<Button
android:id="@+id/btn_mvc_mode"
android:layout_marginTop="@dimen/dp_40"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MVC模式" />
<Button
android:id="@+id/btn_mvp_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MVP模式" />
</LinearLayout>
2.使用mvc模式
MVCModel.class
package com.jyr.kotlindemo.designPatterns.mvc
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
import kotlin.random.Random
class MVCModel {
//请求接口:获取账户的数据(次数模拟网络请求)
public fun getAccountData(accountName: String, callBack: CallBack) {
//随机一个boolean
val random = Random
val nextBoolean = random.nextBoolean()
if (nextBoolean) {
//成功的话,返回用户信息
val account = Account()
account.accountName = accountName
account.level = 100
callBack.onSuccess(account)
} else {
callBack.onFail()
}
}
}
MVCActivity.class
package com.jyr.kotlindemo.designPatterns.mvc
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.jyr.kotlindemo.R
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
/**
* MVC
* model (请求网络数据) !!!!!!!!!!!!!新建model类
* view (指的layout,view控件)
* controller (指的activity,fragment)
*
* 1.需要新建一个接口,callback,里边定义onSuccess和onFail方法
* 2.新建model类(来请求网络数据),里边getData方法,传进去一个callback,如果数据请求成功的话,就回调onSuccess,失败就回调onFail
* 3.在activity中声明Model,并初始化,在需要网络请求的地方,通过model.getData,在onSuccess和onFail的回调里,设置UI
* */
class MVCActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var etCountId: EditText
private lateinit var btnGetInfo: Button
private lateinit var tvUserAccountInfo: TextView
private lateinit var mvcModel: MVCModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_m_v_c)
//初始化控件
etCountId = findViewById<EditText>(R.id.et_account_id)
btnGetInfo = findViewById<Button>(R.id.btn_get_info)
tvUserAccountInfo = findViewById<TextView>(R.id.tv_user_account_info)
btnGetInfo.setOnClickListener(this)
mvcModel = MVCModel()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.btn_get_info -> {
mvcModel.getAccountData(getUserInputAccount(), object : CallBack {
override fun onSuccess(account: Account) {
showSuccessPage(account)
}
override fun onFail() {
showFailPage()
}
})
}
}
}
//获取用户输入的信息
fun getUserInputAccount(): String {
return etCountId.text.toString()
}
//展示获取数据成功的界面
fun showSuccessPage(account: Account) {
tvUserAccountInfo.setText("用户名为${account.accountName},用户等级为${account.level}")
}
//展示获取数据失败的界面
fun showFailPage() {
tvUserAccountInfo.setText("获取用户信息失败")
}
}
activity_m_v_c.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/dp_20"
tools:context=".designPatterns.ModelActivity">
<TextView
android:id="@+id/tv_mode_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MVC模式下"
android:textColor="@color/black"
android:textSize="@dimen/sp_18" />
<EditText
android:id="@+id/et_account_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入账号"
android:maxLines="1" />
<Button
android:id="@+id/btn_get_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_20"
android:text="获取用户信息" />
<TextView
android:id="@+id/tv_user_account_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_20"
android:text="用户信息:" />
</LinearLayout>
3.mvp模式
MVPModel.class
package com.jyr.kotlindemo.designPatterns.mvp
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
import kotlin.random.Random
class MVPModel {
//请求接口:获取账户的数据(次数模拟网络请求)
public fun getAccountData(accountName: String, callBack: CallBack) {
//随机一个boolean
val random = Random
val nextBoolean = random.nextBoolean()
if (nextBoolean) {
//成功的话,返回用户信息
val account = Account()
account.accountName = accountName
account.level = 100
callBack.onSuccess(account)
} else {
callBack.onFail()
}
}
}
IMVPView接口
package com.jyr.kotlindemo.designPatterns.mvp
import com.jyr.kotlindemo.designPatterns.Account
interface IMVPView {
//获取用户输入的信息
fun getUserInputAccount(): String
//展示获取数据成功的界面
fun showSuccessPage(account: Account)
//展示获取数据失败的界面
fun showFailPage()
}
MVPPresenter.class
package com.jyr.kotlindemo.designPatterns.mvp
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
class MVPPresenter {
private var mvpModel: MVPModel
private var imvpView: IMVPView
constructor(imvpView: IMVPView) {
this.imvpView = imvpView
mvpModel = MVPModel()
}
fun getData(account: String) {
mvpModel.getAccountData(account, object : CallBack {
override fun onSuccess(account: Account) {
imvpView.showSuccessPage(account)
}
override fun onFail() {
imvpView.showFailPage()
}
})
}
}
MVPActivity.class
package com.jyr.kotlindemo.designPatterns.mvp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.jyr.kotlindemo.R
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
import com.jyr.kotlindemo.designPatterns.mvc.MVCModel
/**
* MVP
* model (请求网络数据) !!!!!!!!!!!!!新建model类
* view (指的layout,view控件)!!!!!!!!!!新建view类
* presenter (指的activity,fragment)!!!!!!m层和p层的桥梁
*
* m层和v层不直接交互,通过presenter来作为沟通的桥梁
* 用户点击页面,p通知m去请求数据,m请求数据完成后把结果回调给p,p再告诉v,v再去显示页面
* 全程m和v层没有直接交流
*
* 1.需要新建一个接口,callback,里边定义onSuccess和onFail方法
* 2.新建model类(来请求网络数据),里边getData方法,传进去一个callback,如果数据请求成功的话,就回调onSuccess,失败就回调onFail
* 3.新建IView接口,里边定义页面显示的一些方法(showSuccessPage,showFailPage)
* 4.新建一个presenter类,声明model和view,在构造方法里,传进来参数view,实例化model
* 创建一个getData的方法,里边调用model的getData方法,然后在成功和失败的回调里,用view层设置页面
* 5.在activity里声明Presenter,并初始化,在需要网络请求的地方,通过Presenter.getData
* 在activity中实现view接口,重写它的方法,在这些重写的方法里设置UI
*
*
* MVC和MVP的区别(mvc和mvp的优缺点)
* mvc的话,m和v还是可以直接交互的,代码还是耦合比较高,一些逻辑简单的页面可以使用mvc
* mvp的话,例如点击页面,v通知p,p通知m去获取数据,m获取数据之后把结果传给p,p再传给v
* m层和v层不能直接交互,他们之间需要通过presenter来作为桥梁沟通
* 降低了代码的耦合性,但是也会增加一些类
*
*
* MVVM的话,就是在MVP的基础上,增加了数据的双向绑定,数据绑定是通过databinding来实现的
* */
class MVPActivity : AppCompatActivity(), View.OnClickListener, IMVPView {
private lateinit var tvModeName: TextView
private lateinit var etCountId: EditText
private lateinit var btnGetInfo: Button
private lateinit var tvUserAccountInfo: TextView
private lateinit var mvpPresenter: MVPPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_m_v_c)
//初始化控件
tvModeName = findViewById(R.id.tv_mode_name)
etCountId = findViewById<EditText>(R.id.et_account_id)
btnGetInfo = findViewById<Button>(R.id.btn_get_info)
tvUserAccountInfo = findViewById<TextView>(R.id.tv_user_account_info)
btnGetInfo.setOnClickListener(this)
tvModeName.setText("MVP模式")
mvpPresenter = MVPPresenter(this)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.btn_get_info -> {
mvpPresenter.getData(getUserInputAccount())
}
}
}
override fun getUserInputAccount(): String {
return etCountId.text.toString()
}
override fun showSuccessPage(account: Account) {
tvUserAccountInfo.setText("用户名为${account.accountName},用户等级为${account.level}")
}
override fun showFailPage() {
tvUserAccountInfo.setText("获取用户信息失败")
}
}
activity_m_v_c.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/dp_20"
tools:context=".designPatterns.ModelActivity">
<TextView
android:id="@+id/tv_mode_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MVC模式下"
android:textColor="@color/black"
android:textSize="@dimen/sp_18" />
<EditText
android:id="@+id/et_account_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入账号"
android:maxLines="1" />
<Button
android:id="@+id/btn_get_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_20"
android:text="获取用户信息" />
<TextView
android:id="@+id/tv_user_account_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_20"
android:text="用户信息:" />
</LinearLayout>