No Kotlin basic friends advanced here → Koltin basic article

Implementation of Kotlin network model → Implementation of Kotlin network model

1. Why use MVP for project development

Let’s talk about MVC. MVC is a great model, but as projects get bigger and bigger, MVC doesn’t work very well on Android. The Activity takes on a lot of responsibility, both for the view and also for the control layer, sometimes with the Model. If the single responsibility principle is violated, it is common for large projects, if you use MVC, to have thousands of lines of code in an Activity, and MVP is bornIn the process of development, also is not to say that we have to use the MVP, architectural patterns without must be used and need not, only have the right not appropriate, according to the project to choose the right architecture model, is the thought that good programmers do, such as very small project There is no need to use the MVP, MVP shortcomings to write a lot of interface and implementation classes more troublesome, Implementing a small project with MVP is a waste of time. The larger the project, the more modules in the project, so with MVP it is easy to achieve hierarchy and decoupling, compared to MVC is easier to maintain

2. Design of interfaces and implementation classes

So just to help you understand, let me draw a picture

2.1 Implementation of View layer

The View layer is only responsible for data presentation, sends network request commands to the Presenter layer, and receives data from the Presenter layer to call BaseActivity

//P extends BasePresenter KT P:IBasePresenter
//P extends BasePresenter &Serializable KT class BaseActivity

:AppCompatActivity() where P:IBasePresenter,P:Serializable

abstract class BaseActivity<P:IBasePresenter> :AppCompatActivity() {lateinit var presenter:P override fun onCreate(savedInstanceState: Bundle?). { super.onCreate(savedInstanceState) presenter=createP() setContentView(getLayoutID()) } abstract fun getLayoutID(a): Int abstract fun createP(a): P override fun onDestroy(a) { super.onDestroy() recycle() } abstract fun recycle(a) } Copy the code

LoginView

/ / the View layer
interface LoginView {
    // Display the result in the Activity/Fragment layer
    fun loginSuccess(loginBean:LoginResponse?).
    fun loginFialure(errorMsg:String?).

}
Copy the code

LoginActivity

class LoginActivity : BaseActivity<LoginPresenter>(),LoginView {


    private lateinit var mMediaPlayer:MediaPlayer
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        initView()
    }

    private fun initView(a) {
       user_login_bt.setOnClickListener {

           doLogin()
       }
    }

    private fun doLogin(a) {
        val userName=user_phone_et.text.toString()
        val pwd=user_password_et.text.toString()
        // Only the P layer is concerned
        presenter.loginAction(this@LoginActivity,userName,pwd)
/ /.
    }
    override fun getLayoutID(a): Int = R.layout.activity_login

    override fun createP(a): LoginPresenter =LoginPresenterImpl(this)

    override fun recycle(a) {
        presenter.unAttachView()
    }

    override fun loginSuccess(loginBean: LoginResponse?). {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        Toast.makeText(this@LoginActivity."Login successful hey hey ~",Toast.LENGTH_SHORT).show()
    }

    override fun loginFialure(errorMsg: String?). {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        Toast.makeText(this@LoginActivity,errorMsg,Toast.LENGTH_SHORT).show()
    }
}

Copy the code

2.2 Implementation of Presenter layer

The Model and View layers are completely separated by the Presenter class. In order for the Model to be associated with the View, the Presenter must get IBasePrensenter from the Model and View layers

interface IBasePresenter {
// fun attachView()
    // The view is gone
    fun  unAttachView(a)
}
Copy the code

LoginPresenter

/ / Presenter layer
interface LoginPresenter:IBasePresenter {
    / / login
    fun loginAction(context:Context,userName:String,password:String)

    // Listen for callbacks
    interface  OnLoginListener{
        fun loginSuccess(loginBean: LoginResponse?).
        fun loginFialure(errrMsg:String?).}}Copy the code

LoginPresenterImpl

// The P layer is required to get both the Model and View
class LoginPresenterImpl(var loginView: LoginView?) :LoginPresenter,LoginPresenter.OnLoginListener {
    
    //Model Request server
    private val loginModel=LoginModelImpl()
    // View to update UI

    override fun loginAction(context: Context, userName: String, password: String) {
        // TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        // Do a lot of things to check
        // TODO calls the model layer
        loginModel.login(context,userName,password,this)}// Receive the results of the Model
    override fun loginSuccess(loginBean: LoginResponse?). {
     // TODO("not Implemented ") Verifies the result set
        / /...
        // Call back to the View layer to update the UIloginView? .loginSuccess(loginBean) }override fun loginFialure(errrMsg: String?). {
        // TODO("not Implemented ") Verifies the result set
        / /...
        // Call back to the View layer to update the UIloginView? .loginFialure(errrMsg) }override fun unAttachView(a) {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        loginView= null
        loginModel.cancelRequest()
    }
}
Copy the code

2.3 implementation of Model layer

LoginModel

Interface LoginModel {fun cancelRequest() // login fun login(context: The Context, the userName: String, password: String, / / the result callback to P layer onLoginListener: LoginPresenter. OnLoginListener)}Copy the code

LoginModelImpl makes the network request here and calls the result back to the Presenter

class LoginModelImpl :LoginModel{
    override fun cancelRequest(a) {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun login(
        context: Context,
        userName: String,
        password: String,
        onLoginListener: LoginPresenter.OnLoginListener
    ) =
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        APIClient.instance.instanceRetrofit(WanAndroidAPI::class.java)
            .loginAction(userName,password)
            .subscribeOn(Schedulers.io())// Network requests are made in the IO thread
            .observeOn(AndroidSchedulers.mainThread())// Update UI on main thread
            .subscribe(object: APIResponse<LoginResponse>(context){
                override fun onSuccess(data: LoginResponse?). {

                    onLoginListener.loginSuccess(data)}override fun onFailure(errorMsg: String?). {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
// Toast.makeText(this@LoginActivity,errorMsg,Toast.LENGTH_SHORT).show()
                    // Call back to layer P
                    onLoginListener.loginFialure(errorMsg)
                }

            })

}
Copy the code

This is the same as a simple version of Kotlin version of MVP mode login function is completed, the layer is very clear, can be dismantled freely test, maintenance is better than MVC maintenance

3, summarize

In this article, we are familiar with the characteristics and shortcomings of the MVP mode, and also use Kotlin to achieve the MVP version of the login, or mainly familiar with the feeling of developing projects with Kotlin, if there is a mistake, please point out in the comments section, XDM one key three!