Kotlin+Retrofit+Okhttp+MVP architecture construction and sample code

The address of this article: https://blog.csdn.net/qq_40785165/article/details/113200783 , this address must be attached to reprint

Hello everyone, I am Xiao Hei, a programmer who is not yet bald~~~

I've been really busy lately, so busy that I don't want to write a blog, but it's still the old saying--Since I have chosen a far place, I have to worry about both wind and rain.

Today’s content is the construction of Kotlin+Retorfit+Okhttp+MVP architecture. Because of the construction of Kotlin+Retrofit+Okhttp, there are already cases in my previous blog. Those who need it can jump to the article address to view, so the focus of this article Introduction to the code in the MVP architecture

The demo address involved in this article: project address , which contains all the knowledge points involved in the title, small partners in need can go to see the project source code, the function of Demo is to view the data list after successful login, or log out , The running effect of Demo and the project directory structure are as follows

I have also written a blog about Kotlin+MVC before, and interested friends can go to the article address to view the original text

The View layer in MVC refers to custom views written in xml code or Java code, and the Control layer refers to Activity/Fragment. The View layer can directly interact with the Model. The work of updating the UI is performed in the Control layer, but the MVP architecture The View layer refers to Activity/Fragment. The View layer can only interact with the Model through the Presenter layer, or the Presenter layer is used as a bridge between the View and the Model. The View layer calls the Model layer interface for data processing through the Presenter layer. At the end of execution, the result callback is notified to the Presenter layer, and the Presenter layer uses the callback to notify the View layer to update the UI. From the code point of view, MVC is easier to understand, but the code is prone to bloat, and MVP is prone to produce too many classes and interfaces, but the division of labor is clear. Easy to expand. The above is my personal understanding. If you have different opinions, please let me know in the comments section below!

At the beginning of the text, the following takes the login function in the effect as an example (please read the project source code for the exit and list function codes), the interface calls the open API of wanandroid

(1) View layer code

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>

The code of LoginActivity.kt is as follows. Activity inherits the LoginView interface, implements the UI update method, and is easy to interact with the Model through Presenter and accept callbacks.

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()
    }
}

The LoginView.kt code is as follows, defines various functions that need to update the UI, and is used by the P layer to call these functions to notify the UI update

/**
 * 用来View层更新UI的接口
 */
interface LoginView {
    /**
     * 显示加载中提示
     */
    fun showLoading()

    /**
     * 隐藏加载中提示
     */
    fun hideLoading()

    /**
     * 登陆成功的UI更新
     */
    fun loginSuccess()

    /**
     * 登录失败的UI更新
     */
    fun loginFail(msg: String?)

}

(2) Presenter layer code

 

The code of ILoginPresenter.kt is as follows, which defines the method that the Presenter layer needs to call. In this method, logical processing or calling Model is also convenient for expansion

/**
 * P层作为view与model的媒介,需要的接口方法
 */
interface ILoginPresenter {
    fun login(account: String, password: String)
}

The LoginPresenterImpl.kt code is as follows, which implements the interface method in ILoginPresenter, and implements the callback method agreed by the Model layer, calls the Model layer for data processing, and the Presenter layer acts as middleware, so you need to hold the objects of the View layer and the Model layer.

/**
 * 作为媒介联系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)
    }
}

(3) Model layer code

The code of ILoginModel.kt is as follows, which is also an interface that defines the name of the data processing function

/**
 * 处理数据的接口方法
 */
interface ILoginModel {
    fun login(account: String, password: String, loginListener: LoginListener)
}

The LoginModel.kt code is as follows, to implement the interface function, use retrofit+okhttp to make a login request, and notify the Presenter layer of the result through a callback. The retrofit code is not posted here, you can go to the project address to view the project source code

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)
                    }
                }


            })
    }
}

So far, the MVP architecture has been successfully built. Because I am also a learner, the article cannot play a major role in teaching. At present, it can only be used as a record and note. Therefore, if there are any inappropriate points in the article, please comment on the area. Point it out, let's discuss together and make progress together! Thank you for your support and reading!

Guess you like

Origin blog.csdn.net/qq_40785165/article/details/113200783