基于Kotlin的MVP基础封装
Posted 刘望舒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Kotlin的MVP基础封装相关的知识,希望对你有一定的参考价值。
真爱,请置顶或星标
这段时间在写基于gank API客户端Demo的时候,尝试着封装了一把MVP,下面就来谈谈这整个过程中的一些感想。
MVP
说起MVP,大家都是熟悉的不能再熟悉的了,但是要封装一套好的MVP还是很有必要的,可以很快捷的开发项目。接着简单提一下我对MVP的个人理解吧(白话文^-^)。
View层:取数据和显示界面,问P层索要数据,在界面上显示数据。
Presenter层:把View需要的操作传递给Model层,然后Model层处理完复杂操作之后通过P层来把结果传递给View层。
Model层:P层让我干什么我就干什么,有什么用和怎么用不需要管,只管处理,然后把处理后的结果回调给P层。
了解了三者的基本关系之后,接着来看看具体如何封装属于自己的MVP结构。我这里是按照自己的需求,大家仅供参考!
Demo整体结构如下:
整个项目按照上图结构设计。
下面介绍两个比较重要的地方:IBaseView
和BasePresenter
IBaseView:
其中IBaseView
里面写了两个通用方法:在请求网络的时候用到的通用方法,显示和隐藏进度条。
1interface IBaseView{
2 fun showLoading()
3
4 fun hideLoading()
5
6}
当我们在实现具体I***View
时,只需继承它就行了,不必每次都把showLoading
和hideLoading
写一遍,如:
1interface IMainView : IBaseView {
2 fun showandroidData(bean: AndroidBean)
3
4 fun showErrorMsg(msg: String = "亲,网络出现问题了哦~")
5}
这是demo中的一个,另外定义了两个方法,一个是展示获取的Android数据,还有一个就是获取数据失败的方法。显示和隐藏进度条就交给IBaseView
来实现。
BasePresenter:
而BasePresenter
里面实现了P层和V层的绑定和解绑,这里需要知道,在MVP结构中,P和V是双向绑定的,如果我们只绑定不解绑的话,在activity
已经销毁的情况下,Presenter
如果还在执行操作,那么就会造成activity
无法被释放的问题,产生内存泄漏。所以这里一定要注意P和V的解绑,具体实现是在BaseActivity
中统一处理。具体代码如下:
1package com.taonce.kotlindemo.base
2
3open class BasePresenter<V> {
4
5 private var view: V? = null
6
7 // 绑定View
8 fun attachView(view: V) {
9 this.view = view
10 }
11
12 // 解绑
13 fun detachView() {
14 this.view = null
15 }
16
17 fun isAttach(): Boolean {
18 return view != null
19 }
20
21}
同IBaseView
一样,在实现具体的***Presenter
的时候,也只需要继承BasePresenter
就ok了。只需要另外加上自己的逻辑,不考虑每次的V和P的解绑。如:
1package com.taonce.kotlindemo.presenter
2
3import com.taonce.kotlindemo.base.BasePresenter
4import com.taonce.kotlindemo.bean.AndroidBean
5import com.taonce.kotlindemo.model.MainModel
6import com.taonce.kotlindemo.contract.IMainModel
7import com.taonce.kotlindemo.contract.IMainView
8
9class MainPresenter(mView: IMainView) : BasePresenter<IMainView>(), IMainModel.OnGetAndroidDataListener {
10
11 private var mView: IMainView? = mView
12 private var mModel: IMainModel? = null
13
14 init {
15 mModel = MainModel()
16 }
17
18 fun getAndroidData(category: String, page: Int) {
19 this.mView?.showLoading()
20 this.mModel?.getAndroidData(category, page, this)
21 }
22
23 override fun onGetAndroidDataFinished(bean: AndroidBean?) {
24 this.mView?.hideLoading()
25 if (bean != null) {
26 mView?.showAndroidData(bean)
27 if (bean.error == "true") {
28 mView?.showErrorMsg()
29 }
30 } else {
31 mView?.showErrorMsg()
32 }
33 }
34
35}
BaseActivity
在BaseActivity
除了日常的getLayoutId()
initView()
initData()
initEvent()
四个抽象方法之外,主要还是封装了通用的进度条的显示和隐藏,P层和V层的绑定和解绑。
通过实现IBaseView接口,把里面的方法进行重写,调用
showLoadingView()
和hideLoadingView()
方法。通过泛型来实现P层的引用,然后通过
abstract fun getPresenter(): T
来得到具体的Presenter
,这样就可以在onCreate()
方法里面对P和V进行绑定,在onDestory()
方法里对P层引用的View
进行释放。
具体代码如下:
1package com.taonce.kotlindemo.base
2
3import android.support.v7.app.AppCompatActivity
4import android.os.Bundle
5import com.taonce.kotlindemo.R
6import com.taonce.kotlindemo.ui.inter.IBaseView
7
8abstract class BaseActivity<V, T : BasePresenter<V>> : AppCompatActivity(), IBaseView {
9
10 private var baseLoadingView: BaseLoadingView? = null
11 private var basePresenter: T? = null
12
13 override fun onCreate(savedInstanceState: Bundle?) {
14 super.onCreate(savedInstanceState)
15 setContentView(getLayoutId())
16 basePresenter = getPresenter()
17 basePresenter?.attachView(this as V)
18 initLoadingView()
19 initView()
20 initData()
21 initEvent()
22 }
23
24 abstract fun getLayoutId(): Int
25
26 abstract fun initData()
27
28 abstract fun initView()
29
30 abstract fun initEvent()
31
32 abstract fun getPresenter(): T
33
34
35 override fun onResume() {
36 super.onResume()
37 }
38
39 override fun onDestroy() {
40 super.onDestroy()
41
42 // 销毁dialog
43 if (null != baseLoadingView && baseLoadingView!!.isShowing) {
44 baseLoadingView?.dismiss()
45 }
46 baseLoadingView = null
47
48 // 在activity销毁时,解绑activity和presenter
49 if (basePresenter != null) {
50 basePresenter?.detachView()
51 basePresenter = null
52 }
53 }
54
55 override fun onStop() {
56 super.onStop()
57 }
58
59 override fun onPause() {
60 super.onPause()
61 }
62
63 private fun initLoadingView() {
64 baseLoadingView = BaseLoadingView(this, R.style.transparent_dialog)
65 }
66
67 private fun showLoadingView() {
68 if (null != baseLoadingView) {
69 baseLoadingView?.show()
70 } else {
71 initLoadingView()
72 baseLoadingView?.show()
73 }
74 }
75
76 private fun hideLoadingView() {
77 if (null != baseLoadingView && baseLoadingView!!.isShowing) {
78 baseLoadingView?.cancel()
79 }
80 }
81
82 /**
83 * 将显示dialog和取消dialog放在了基础类中
84 */
85 override fun showLoading() {
86 showLoadingView()
87 }
88
89 override fun hideLoading() {
90 hideLoadingView()
91 }
92}
网络
网络部分主要采用的是OkHttp3+Retrofit2的方式,通过OKHttp3
设置公共头参、Log输出、超时连接等,Retrofit2
是用来进行网络请求,最终的线程转换是通过RxJava来实现的,由于网络这块还没深入去探究,暂时只简单封装了一下,后期会在此基础上完善。具体的代码会在文末贴上链接。
— — — END — — —
分享大前端、Java和前沿技术
关注职业发展和行业动态。
以上是关于基于Kotlin的MVP基础封装的主要内容,如果未能解决你的问题,请参考以下文章