本文地址:https://blog.csdn.net/qq_40785165/article/details/113200783,转载需附上此地址
大家好,我是小黑,一个还没秃头的程序员~~~
最近是真的忙,忙到不想写博客,但是还是那句老话--既然选择了远方,便只顾风雨兼程。
今天的内容是Kotlin+Retorfit+Okhttp+MVP架构的搭建,由于Kotlin+Retrofit+Okhttp的搭建我之前的博客中已经有案例了,有需要的小伙伴可以跳转至文章地址查看,所以本文的重点在于MVP架构的代码介绍
本文章涉及的Demo地址:项目地址,里面有标题中涉及到的所有知识点,有需要的小伙伴可以去看看项目源码,Demo的功能为登录成功后可进行查看数据列表,也可退出登录,Demo的运行效果以及项目目录结构如下所示
我之前也有写过Kotlin+MVC的博客,感兴趣的小伙伴可以去文章地址查看原文
MVC中View层指的是xml代码或者Java代码写的自定义view,Control层指的是Activity/Fragment,View层可以直接与Model进行交互,更新UI的工作都是在Control层执行,但是MVP架构中View层指的就是Activity/Fragment,View层只能通过Presenter层和Model进行交互,或者说Presenter层是作为View与Model的桥梁,View层通过Presenter层调用Model层的接口进行数据处理,Model层执行结束将结果回调通知Presenter层,Presenter层通过回调通知View层进行UI更新,从代码而言,MVC更容易易懂,但是代码容易臃肿,MVP容易产生过多的类和接口,但是分工明确,易于拓展。以上是我个人的理解,若有不同见解,欢迎底下评论区多多指教!
正文开始,以下以效果中的登录功能为例(退出以及列表功能代码请阅读项目源码),接口调用wanandroid的开放Api
(一)View层代码
activity_login.xml
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-
android:layout_width=
"match_parent"
-
android:layout_height=
"match_parent"
-
android:orientation=
"vertical">
-
-
<LinearLayout
-
android:layout_width=
"match_parent"
-
android:layout_height=
"wrap_content">
-
-
<TextView
-
android:layout_width=
"wrap_content"
-
android:layout_height=
"wrap_content"
-
android:text=
"账号:" />
-
-
<EditText
-
android:id=
"@+id/et_account"
-
android:layout_width=
"match_parent"
-
android:layout_height=
"wrap_content"
-
android:hint=
"请输入账号"
-
android:inputType=
"text"
-
android:text=
"" />
-
</LinearLayout>
-
-
<LinearLayout
-
android:layout_width=
"match_parent"
-
android:layout_height=
"wrap_content">
-
-
<TextView
-
android:layout_width=
"wrap_content"
-
android:layout_height=
"wrap_content"
-
android:text=
"密码:" />
-
-
<EditText
-
android:id=
"@+id/et_password"
-
android:layout_width=
"match_parent"
-
android:layout_height=
"wrap_content"
-
android:hint=
"请输入密码"
-
android:inputType=
"text"
-
android:text=
"" />
-
</LinearLayout>
-
-
<TextView
-
android:id=
"@+id/tv_login"
-
android:layout_width=
"@dimen/dp_40"
-
android:layout_height=
"@dimen/dp_40"
-
android:layout_gravity=
"center"
-
android:layout_marginTop=
"@dimen/dp_40"
-
android:background=
"#c0c0c0"
-
android:gravity=
"center"
-
android:text=
"登录"
-
android:textColor=
"#000" />
-
-
</LinearLayout>
LoginActivity.kt代码如下,activity继承了LoginView接口,实现更新UI方法,易于通过Presenter与Model进行交互并接受回调
-
class LoginActivity : AppCompatActivity(), LoginView {
-
private
val loginModel: LoginModel
by lazy {
-
LoginModel()
-
}
-
private
val loginPresenterImpl: ILoginPresenter
by lazy {
-
LoginPresenterImpl(
this, loginModel)
-
}
-
-
override
fun onCreate(savedInstanceState: Bundle?) {
-
super.onCreate(savedInstanceState)
-
setContentView(R.layout.activity_login)
-
initListener()
-
}
-
-
private
fun initListener() {
-
tv_login.setOnClickListener {
-
loginPresenterImpl.login(et_account.text.toString(), et_password.text.toString())
-
}
-
}
-
-
override
fun showLoading() {
-
Toast.makeText(
this,
"登录加载中", Toast.LENGTH_SHORT).show()
-
}
-
-
override
fun hideLoading() {
-
Toast.makeText(
this,
"登录加载结束", Toast.LENGTH_SHORT).show()
-
}
-
-
override
fun loginSuccess() {
-
Toast.makeText(
this,
"登录成功", Toast.LENGTH_SHORT).show()
-
var intent = Intent(
this, MainActivity::
class.java)
-
startActivity(intent)
-
finish()
-
}
-
-
override
fun loginFail(msg: String?) {
-
Toast.makeText(this,
"登录失败", Toast.LENGTH_SHORT).show()
-
}
-
}
LoginView.kt代码如下,定义了各种需要更新UI的函数,用于P层调用这些函数进行通知UI更新
-
/**
-
* 用来View层更新UI的接口
-
*/
-
interface LoginView {
-
/**
-
* 显示加载中提示
-
*/
-
fun showLoading()
-
-
/**
-
* 隐藏加载中提示
-
*/
-
fun hideLoading()
-
-
/**
-
* 登陆成功的UI更新
-
*/
-
fun loginSuccess()
-
-
/**
-
* 登录失败的UI更新
-
*/
-
fun loginFail(msg: String?)
-
-
}
(二)Presenter层代码
ILoginPresenter.kt代码如下,定义了Presenter层需要调用的方法,在该方法里进行逻辑处理或者调用Model,也方便拓展
-
/**
-
* P层作为view与model的媒介,需要的接口方法
-
*/
-
interface ILoginPresenter {
-
fun login(account: String, password: String)
-
}
LoginPresenterImpl.kt代码如下,实现了ILoginPresenter中的接口方法,并实现Model层约定的回调方法,调用Model层进行数据处理,Presenter层作为中间件,所以需要持有View层与Model层的对象
-
/**
-
* 作为媒介联系view与model,view和model各司其职互不干扰,等待model返回回调,present再去通知view层进行UI更新
-
*/
-
class LoginPresenterImpl(loginView: LoginView, iLoginModel: ILoginModel) : ILoginPresenter,
-
LoginListener {
-
private
var loginView: LoginView? =
null
-
private
var loginModel: ILoginModel? =
null
-
-
init {
-
this.loginModel = iLoginModel
-
this.loginView = loginView
-
}
-
-
override
fun login(account: String, password: String) {
-
loginView?.showLoading()
-
loginModel?.login(account, password,
this)
-
}
-
-
override
fun loginSuccess() {
-
loginView?.hideLoading()
-
loginView?.loginSuccess()
-
}
-
-
override
fun loginFail(msg: String?) {
-
loginView?.hideLoading()
-
loginView?.loginFail(msg)
-
}
-
}
(三)Model层代码
ILoginModel.kt代码如下,也是一个接口,定义数据处理函数名
-
/**
-
* 处理数据的接口方法
-
*/
-
interface ILoginModel {
-
fun login(account: String, password: String, loginListener: LoginListener)
-
}
LoginModel.kt代码如下,实现接口函数,使用retrofit+okhttp进行登录请求,并且将结果通过回调通知Presenter层,retrofit代码这里就不贴出来了,可以前往项目地址查看项目源码
-
class LoginModel : ILoginModel {
-
override
fun login(account: String, password: String, loginListener: LoginListener) {
-
HttpHelper.getApi()?.login(account, password)
-
?.enqueue(
object : SingleCallback<Result<UserBean>>() {
-
override
fun onSuccess(response: Result<UserBean>) {
-
if (
"0".equals(response.errorCode)) {
-
loginListener.loginSuccess()
-
}
else {
-
loginListener.loginFail(response.errorMsg)
-
}
-
}
-
-
-
})
-
}
-
}
到此为止,MVP架构就搭建成功了,因为自己本身也是个学习者,所以文章不能起到太大教学作用,目前只能作为记录以及笔记使用,所以文章中有不妥之处欢迎大家评论区指出来,大家共同讨论,共同进步!谢谢大家的支持与阅读!
转载:https://blog.csdn.net/qq_40785165/article/details/113200783