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!