美文网首页
造一个mvp的轮子

造一个mvp的轮子

作者: 折青梅 | 来源:发表于2020-07-10 10:41 被阅读0次

前言:虽然现在已经mvvm了,但是mvp对于新鸟来说,还是一个不错的入门级开发框架,这里就造一个lifecycle的mvp。

起初:mvp的轮子有很多了。大多数情况下是在activity/fragment的生命周期绑定presenter,然后在生命周期内初始化,或者释放,我这个轮子也没有什么特别的地方,也是遵循这一套,最近在看了MvpArm的源码设计后,由于本人太菜,不太会dagger2,又很欣赏arm中以lifecycle绑定presenter的做法,所以将dagger2抽离,造了个简易的lifecycle绑定presenter的轮子

这是MVPArms,个人觉得这确实是个不错的快速开发框架,里面集成了基本全部的开发所需,而且作者还提供了插件,掌握的话,可以节约很多开发时间和改bug时间来干自己想干的事

找工作.jpg

BaseActivity/BaseFragment

直接上代码


/**
 * baseActivity基类
 * 视图层,可自行拓展沉浸式等
 * 如果定义增多,建议新增IActivity接口以做规范
 */
abstract class BaseActivity : RxAppCompatActivity(), LifecycleObserver {
    private var mUnbinder: Unbinder? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(getLayout())
        mUnbinder = ButterKnife.bind(this)
        if (useEventBus()) {
            //register event
        }
        initView()
    }

    /**
     * 布局的layout
     */
    abstract fun getLayout(): Int

    /**
     * 是否使用eventBus
     */
    abstract fun useEventBus(): Boolean

    /**
     * 视图回调,这里是子类的开始
     */
    abstract fun initView()

    override fun onDestroy() {
        super.onDestroy()
        if (mUnbinder != null && mUnbinder !== Unbinder.EMPTY) {
            mUnbinder!!.unbind()
        }
        mUnbinder = null
        if (useEventBus()) {
            // unRegister event
        }
    }
}

BaseFragment同理,这两个基类是基础继承,在不使用mvp的时候,直接继承即可,base的作用不必多说,里面可以封装自己项目的逻辑

然后是

BaseMvpActivity(BaseMvpFragment)


/**
 * mvp
 */
abstract class BaseMvpActivity<P : IPresenter> : BaseActivity(), IView {
    private var mPresenter: P? = null

    /**
     * onCreate中创建presenter
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mPresenter = setUpPresenter()
    }

    /**
     * 默认不使用eventBus
     */
    override fun useEventBus(): Boolean {
        return false
    }

    abstract fun setUpPresenter(): P?

    override fun onDestroy() {
        super.onDestroy()
        mPresenter?.onDestroy()
        mPresenter = null
    }

    var mStatusView: MultipleStatusView? = null
    override fun showLoading() {
        if (mStatusView == null) {
            val mViewRoot = window.decorView.findViewById<ViewGroup>(android.R.id.content).getChildAt(0) as ViewGroup
            if (mViewRoot.childCount != 0) {
                for (i in 0 until mViewRoot.childCount) {
                    if (mViewRoot.getChildAt(i) is MultipleStatusView) {
                        mStatusView = mViewRoot.getChildAt(i) as MultipleStatusView
                        mStatusView?.setOnRetryClickListener {
                            onReLoad()
                        }
                        break
                    }
                }
            }
        }
        mStatusView?.showLoading()
    }

    override fun showEmpty() {
        mStatusView?.showEmpty()
    }

    override fun showError() {
        mStatusView?.showEmpty()
    }

    override fun hideLoading() {
        mStatusView?.showContent()
    }

    var mAlertDialog: AlertDialog? = null
    override fun showDialogLoading() {
        mAlertDialog = AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog)
            .setView(R.layout.load_dialog_layout)
            .setCancelable(true).show()
    }

    override fun hideDialogLoading() {
        mAlertDialog?.dismiss()
    }

    override fun onReLoad() {

    }


    override fun showMessage(tipMessage: String?) {
        //Toast this
        Toast.makeText(this, tipMessage, Toast.LENGTH_SHORT).show()
    }

    override fun findActivity(): RxAppCompatActivity {
        return this
    }

    override fun findFragment(): RxFragment? {
        return null
    }
}

BaseMvpActivity/BaseMvpFragment处理presenter的创建,和资源的释放销毁

BasePresenter


/**
 * @author chenke
 * @create 2020/6/30
 * @Describe
 */
public class BasePresenter<M extends IModel, V extends IView> implements IPresenter, LifecycleObserver {
    protected CompositeDisposable mCompositeDisposable;
    protected M mModel;
    protected V mRootView;

    /**
     * 如果当前页面同时需要 Model 层和 View 层,则使用此构造函数(默认)
     *
     * @param model
     * @param rootView
     */
    public BasePresenter(M model, V rootView) {
        this.mModel = model;
        this.mRootView = rootView;
        onStart();
    }

    /**
     * 如果当前页面不需要操作数据,只需要 View 层,则使用此构造函数
     *
     * @param rootView
     */
    public BasePresenter(V rootView) {
        this.mRootView = rootView;
        onStart();
    }

    public BasePresenter() {

    }

    @Override
    public void onStart() {
        //将 LifecycleObserver 注册给 LifecycleOwner 后 @OnLifecycleEvent 才可以正常使用
        if (mRootView != null && mRootView instanceof LifecycleObserver) {
            //activity ,fragment绑定自身生命周期
            ((LifecycleOwner) mRootView).getLifecycle().addObserver(this);
            if (mModel != null && mModel instanceof LifecycleObserver) {
                //activity ,fragment绑定model数据层的生命周期,当Activity销毁时,数据层感知其生命周期
                ((LifecycleOwner) mRootView).getLifecycle().addObserver((LifecycleObserver) mModel);
            }
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy(LifecycleOwner owner) {
        /**
         * 注意, 如果在这里调用了 {@link #onDestroy()} 方法, 会出现某些地方引用 {@code mModel} 或 {@code mRootView} 为 null 的情况
         * 比如在 {@link RxLifecycle} 终止 {@link Observable} 时, 在 {@link io.reactivex.Observable#doFinally(Action)} 中却引用了 {@code mRootView} 做一些释放资源的操作, 此时会空指针
         * 或者如果你声明了多个 @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 时在其他 @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
         * 中引用了 {@code mModel} 或 {@code mRootView} 也可能会出现此情况
         */
        owner.getLifecycle().removeObserver(this);
    }

    public void addDispose(Disposable disposable) {
        if (mCompositeDisposable == null) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);//将所有 Disposable 放入容器集中处理
    }

    /**
     * 停止集合中正在执行的 RxJava 任务
     */
    public void unDispose() {
        if (mCompositeDisposable != null) {
            mCompositeDisposable.clear();//保证 Activity 结束时取消所有正在执行的订阅
        }
    }

    @Override
    public void onDestroy() {
        unDispose();
        if (mModel != null) {
            mModel.onDestroy();
        }
        this.mModel = null;
        this.mRootView = null;
    }
}

activity/fragment 绑定了将生命周期和BasePresenter/Model,绑定,这样当activity/fragment生命周期法伤变化是,,base和model作为观察者

可以,观察到生命周期的变化

核心代码


    @Override
    public void onStart() {
        //将 LifecycleObserver 注册给 LifecycleOwner 后 @OnLifecycleEvent 才可以正常使用
        if (mRootView != null && mRootView instanceof LifecycleObserver) {
            //activity ,fragment绑定自身生命周期
            ((LifecycleOwner) mRootView).getLifecycle().addObserver(this);
            if (mModel != null && mModel instanceof LifecycleObserver) {
                //activity ,fragment绑定model数据层的生命周期,当Activity销毁时,数据层感知其生命周期
                ((LifecycleOwner) mRootView).getLifecycle().addObserver((LifecycleObserver) mModel);
            }
        }
    }

所以BasePresenter和model都要实现lifecycle的观察者接口

public class BasePresenterimplements IPresenter, LifecycleObserver
open class BaseModel : IModel, LifecycleObserver

因为model为数据交互层,所以需要retrofit的实例

BaseModel


/**
 * @author chenke
 * @create 2020/6/30
 * @Describe
 */
open class BaseModel : IModel, LifecycleObserver {
    protected var mRepositoryManager: IRepositoryManager? = null

    /**
     * model层为数据层,所以需要retrofit实例来请求网络
     */
    constructor(repositoryManager: IRepositoryManager) {
        this.mRepositoryManager = repositoryManager
    }

    /**
     * presenter在onDestroy时调用
     * 释放资源
     */
    override fun onDestroy() {
        mRepositoryManager = null
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy(owner: LifecycleOwner) {
        owner.lifecycle.removeObserver(this)
    }
}

现在,我们就用这个简易的生命周期感知mvp来写一个demo吧

界面如下


界面.jpg

xml就忽略了

WeatherActivity mvp的网络请求界面


class WeatherActivity : BaseMvpActivity<TestPresenter>(), TestContact.TestView {

    override fun setUpPresenter(): TestPresenter? {
        return TestPresenter(TestModel(RepositoryManager()), this)
    }

    override fun initView() {

    }

    override fun getLayout(): Int {
        return R.layout.activity_weather_activty
    }


    override fun bindTest(): TextView {
        return tv_content
    }
}

题外话:因为presenter在setContentView初始化,所以在presenter调用时TextView已经完成了初始化

presenter

presenter的创建

    override fun setUpPresenter(): TestPresenter? {
        return TestPresenter(TestModel(RepositoryManager()), this)
    }

这里RepositoryManager是retrofit的实例创建类

RepositoryManager

/**
 * @author chenke
 * @create 2020/6/30
 * @Describe retrofit网络创建层
 */
public class RepositoryManager : IRepositoryManager {

    private val URL_1 = "http://wthrcdn.etouch.cn/"

    var retrofit1 = Retrofit.Builder()
        .baseUrl(URL_1)
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build()


    fun <T> create(serviceClass: Class<T>): T = retrofit1.create(serviceClass)

    private var apiHost1: ApiHost1? = null
    override fun getApiHost1(): ApiHost1 {
        if (apiHost1 == null) {
            apiHost1 = create(ApiHost1::class.java)
        }
        return apiHost1 as ApiHost1
    }

    override fun getApiHost2() {

    }

    override fun getApiHost3() {

    }


}

IRepositoryManager是管理retrofit url接口文件,可以将不同模块的url做拆分,也可以建立不同的baseurl(不同baseurl的retrofit客户端,或者针对每个url接口文件的baseurl通过常量来管理请求)

/**
 * @author chenke
 * @create 2020/6/30
 * @Describe
 */
interface IRepositoryManager {
    /**
     * 对应不同的baseUrl
     */
    fun getApiHost1(): ApiHost1

    fun getApiHost2()

    fun getApiHost3()
}

TestPresente

constructor(model: TestContact.TestModel, rootView: TestContact.TestView) :super(model, rootView)

我们再回过头来看super(model,rootView)

    /**
     * 如果当前页面同时需要 Model 层和 View 层,则使用此构造函数(默认)
     *
     * @param model
     * @param rootView
     */
    public BasePresenter(M model, V rootView) {
        this.mModel = model;
        this.mRootView = rootView;
        onStart();
    }
    @Override
    public void onStart() {
        //将 LifecycleObserver 注册给 LifecycleOwner 后 @OnLifecycleEvent 才可以正常使用
        if (mRootView != null && mRootView instanceof LifecycleObserver) {
            //activity ,fragment绑定自身生命周期
            ((LifecycleOwner) mRootView).getLifecycle().addObserver(this);
            if (mModel != null && mModel instanceof LifecycleObserver) {
                //activity ,fragment绑定model数据层的生命周期,当Activity销毁时,数据层感知其生命周期
                ((LifecycleOwner) mRootView).getLifecycle().addObserver((LifecycleObserver) mModel);
            }
        }
    }

这里onStart()将presenter和model作为activity/fragment的生命周期观察者,一切的根源

现在presenter就可以感知activity的生命周期变化了

TestPresenter.onCreate

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        Log.i("gw", "activity onCreate")
        mRootView.showDialogLoading()
        mModel.getWeather2("成都")
            .delay(2000, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .compose(mRootView.findActivity().bindUntilEvent(ActivityEvent.DESTROY))
            .subscribe(object : Observer<ResponseBean<WeatherBean>> {
                override fun onComplete() {
                    mRootView.hideDialogLoading()
                }

                override fun onSubscribe(d: Disposable) {
                    addDispose(d)
                }

                override fun onError(e: Throwable) {
                    e.printStackTrace()
                    mRootView.bindTest().text = "${e.message}"
                }

                override fun onNext(t: ResponseBean<WeatherBean>) {
                    Log.i("gw", "请求成功")
                    mRootView.showMessage("请求成功")
                    mRootView.bindTest().text = "${t.data.city}"
                }
            })
    }

这里在activityonCreate的时候直接请求了接口数据

然后mRootView(WeatherActivity)来刷新UI展示

效果如下

效果.gif

完整的TestPresenter

TestPresenter

/**
 * @author chenke
 * @create 2020/7/7
 * @Describe
 */
class TestPresenter : BasePresenter<TestContact.TestModel, TestContact.TestView> {

    constructor(model: TestContact.TestModel, rootView: TestContact.TestView) : super(model, rootView)

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        Log.i("gw", "activity onCreate")
        mRootView.showDialogLoading()
        mModel.getWeather2("成都")
            .delay(2000, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .compose(mRootView.findActivity().bindUntilEvent(ActivityEvent.DESTROY))
            .subscribe(object : Observer<ResponseBean<WeatherBean>> {
                override fun onComplete() {
                    mRootView.hideDialogLoading()
                }

                override fun onSubscribe(d: Disposable) {
                    addDispose(d)
                }

                override fun onError(e: Throwable) {
                    e.printStackTrace()
                    mRootView.bindTest().text = "${e.message}"
                }

                override fun onNext(t: ResponseBean<WeatherBean>) {
                    Log.i("gw", "请求成功")
                    mRootView.showMessage("请求成功")
                    mRootView.bindTest().text = "${t.data.city}"
                }
            })
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onActivityDestroy() {
        Log.i("gw", "activity finish")
        Log.i("gw", "mRootView:$mRootView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.i("gw", "presenter销毁了")
        Log.i("gw", "mRootView:$mRootView")
    }
}

接下来,我们观察下log各个生命周期日志

onCreate的时候

onCreate.jpg

WeatherActivity点击回退finish的时候


完整生命周期.jpg

model中感知activity/fragment的生命周期

#TestModel

/**
 * @author chenke
 * @create 2020/7/7
 * @Describe
 */
class TestModel : BaseModel, TestContact.TestModel {
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onActivityDestroy() {
        Log.i("gw", "model感知activity生命周期---finish")
    }

    constructor(repositoryManager: IRepositoryManager) : super(repositoryManager)

    override fun getWeather(): Observable<ResponseBean<WeatherBean>> {
        return mRepositoryManager?.getApiHost1()?.weather()!!
    }

    override fun getWeather2(city: String): Observable<ResponseBean<WeatherBean>> {
        return mRepositoryManager?.getApiHost1()?.weather2(city)!!
    }
}

至此,简易的生命周期感知的mvp就完成了,附上demo,你可以down下来做你想要的修改

生命周期感知MVPDemo

相关文章

网友评论

      本文标题:造一个mvp的轮子

      本文链接:https://www.haomeiwen.com/subject/keepcktx.html