MVP模式在Android中的规范化

标准化MVP模式

不同的人对MVP有不同的层级划分,虽然都做到了数据和业务分离,但没有统一的标准,不利于后续代码的维护和扩展。这里简单对MVP模式在Android中的使用进行一些约定。

MVP模式的基本概述

既然我们要约定一套标准的MVP模式架构,那么首先我们需要对MVP进行简单的说明。

MVP模式由来

MVP从MVC演变而来,通过表示器将视图与模型巧妙地分开。MVP的全称为Model-View-PresenterModel提供数据,View负责显示,Controller/Presenter负责逻辑的处理(以下使用Presenter)。MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过Controller。

MVP各个模块说明

MVP模式中各个模块,独立负责不同的业务逻辑。

  • View,用来表述ActivityFragment等暴露给用户使用的视图,中需要和用户交互的事件变化。
  • Model,用来处理获取服务器数据或本地数据库数据以及一些缓存数据等业务,其中这些数据的操作可以进行更一步的封装,但是调用不能暴露给外部,只能在Model层使用。
  • Presenter,用来获取Model层级的数据,并通过View层级回调给视图窗口使用。

MVP的基本模块约定

通过上述对MVP模式的概述,我们能大致在心中形成一个简单的划分。那么我们现在直接将这个划分进行限定,让在一个项目团队中的每个人都能直接使用这套规则来进行开发。

视图交互View层

我们定义一个IBaseView用来表述基本的视图变化,所有后续使用的VIew层级都需要继承这个基类。

interface IBaseView {
    //TODO: 实现基础的视图交互需求,例如获取Context
    fun getContext(): Context
}

数据获取Model层

我们定义一个IBaseModel用来确认数据获取的地方,所有后续构建的Model层级都需要继承这个基类。

class IBaseModel {
    //TODO: 2020年04月10日15:16:02 实现获取对应的数据
}

业务逻辑处理Presenter层

我们定义一个IBasePresenter用来确认业务逻辑处理的地方,所有后续构建的Presenter层级都需要继承这个基类。

class IBasePresenter(mView: IBaseView) {
    //TODO: 2020年04月10日15:17:24 实现对应视图层逻辑处理
}

视图展示层(Activity或Fragment等)

我们定义一个IBaseMVPActivity用来实现IBaseView,且定义获取Presenter的方法。

abstract class IBaseMVPActivity<out P : IBasePresenter>: AppCompatActivity(), IBaseView {

    override fun getContext(): Context {
        return this
    }

    /**
     * 让presenter只会创建一个
     * */
    val presenter: P by lazy {
        createPresenter()
    }

    /**
     * 生成presenter的方法
     * */
    abstract val createPresenter: () -> P
}

扩展

由于Presenter持有了View,而视图层级实现了View。可能会导致当Activity被销毁时,由于Presenter调用Model层的耗时操作,导致内存泄漏,可以结合rxlifecycle2来处理这个。

且我们可以考虑对PresenterModel之间的交互,增加一个IBaseContact接口来处理。考虑到Activity或FragmentPresenter,可能存在一对多的情况,并在PresenterModel中指定引用的IBaseViewIBaseContact类型,来防止团队协作时传递参数和使用方法的错误的问题。

abstract class BaseModel<out C>(private val contact: C) {//考虑是否在这里限制contact

    /**
     * 用来处理所有的请求
     * */
    private val cmSub by lazy {
        CompositeDisposable()
    }

    /**
     * 销毁网络请求和提示的对话框
     */
    open fun destroy() {
        if (!cmSub.isDisposed) {
            cmSub.dispose()
        }
    }

    /**
     * 增加统一订阅方法,来统一处理请求
     * */
    fun <T> Observable<T>.subc(s: DisposableObserver<T>) {

        if (UserSettingManager.fetchUseNetType() == UserSettingConst.USER_NET_TYPE_NONE) {//仅使用wifi
            QNToastUtils.showShort("设置无法使用网络数据!")
            return
        }

        if (UserSettingManager.fetchUseNetType() == UserSettingConst.USER_NET_TYPE_WIFI) {//仅使用wifi
            //第一次检测网络使用情况
            val netManager = QNUtils.getInstance().app.
                    getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            if (NetChangeManager.checkNetType(netManager, false) != ConnectivityManager.TYPE_WIFI) {
                QNToastUtils.showShort("设置仅使用WIFI网络数据,当前无WIFI连接!")
                return
            }
        }

        if (UserSettingManager.fetchUseNetType() == UserSettingConst.USER_NET_TYPE_3G) {//仅使用3g
            //第一次检测网络使用情况
            val netManager = QNUtils.getInstance().app.
                    getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            if (NetChangeManager.checkNetType(netManager, false) != ConnectivityManager.TYPE_MOBILE) {
                QNToastUtils.showShort("设置仅使用移动网络数据,当前无移动网络数据!")
                return
            }
        }

        this.subscribe(s)
        cmSub.add(s)
    }

}

参考:

https://baike.baidu.com/item/MVP%E6%A8%A1%E5%BC%8F/10961746?fr=aladdin

https://blog.csdn.net/hpp_1225/article/details/80674451

https://www.jianshu.com/p/f3e7deae7281

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值