本文地址: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架構就搭建成功了,因爲自己本身也是個學習者,所以文章不能起到太大教學作用,目前只能作爲記錄以及筆記使用,所以文章中有不妥之處歡迎大家評論區指出來,大家共同討論,共同進步!謝謝大家的支持與閱讀!