美文网首页
MVP基础篇

MVP基础篇

作者: Method | 来源:发表于2021-01-29 13:05 被阅读0次
    js.jpg

    MVC

    简介

    将应用组件分为三部分:模型-视图-控制器

    • 模型(model) 用于封装业务逻辑相关的数据。model层有对数据直接访问的权力,例如数据库访问。model层 不依赖 view层和controller层,也就是说model层,不关心它会被如何显示或是如何操作。但是model层中数据变化一般会通过一种刷新机制被公布。为了实现这种机制,哪些监视model数据的controller层需要事先在此注册,从而观察数据改变
    • 视图(view) 与用户交互,实现数据有目的的显示。view层没有处理逻辑。
    • 控制器(controller) 起到不同层面的组织作用,控制应用程序流程。它处理事件,并做出响应。事件包括:用户操作,数据改变。
    mvc.png

    那在Android里是什么充当View,什么充当Model,什么充当Controller呢?

    View:Acitivity(View)、Fragment(View)视图,在android里xml布局转成View后,加载到了Activity/Fragment里了。

    Controller:Controller对应着Activity/Fragment,绑定UI,处理各种业务。

    Model:数据的获取,存储,更新

    优点

    view与model隔离,view换了,model不影响。model换其他的数据源,view层也不受影响。一个view可以连接多个model,有些model可以复用。比如说你这个页面需要用户信息,另外一个界面也需要用户信息。

    缺点

    这里我们主要指Android上的缺点,不适合在Android开发上使用。在Android开发中,View的相关内容和Controller都写到一起了,==会让Activity/Fragment越来越臃肿==。

    MVP

    简介

    于是大家都觉得MVC套在Android上不好。VC的代码会越来越多,如果要处理复杂的逻辑,Activity的代码上千上行。于是大家开始剥离VC里的代码。

    这个用起来爽了很多,Activity的代码量也没这么多了。

    大量的逻辑代码抽取到了Presenter层。

    • View:Activity、Fragment

    • Presneter:逻辑层

    • Model:数据处理

    怎么调用逻辑层的方法呢?

    View层持有Presenter层的引用或者通过管理类管理Presenter,总之View可以直接拿到Presenter,这样子,View就可以调用Presenter里的方法了。比如说Presenter你给我获取一个这个页面的分类

    Presenter层如何更新UI呢

    当View层去获取/创建Presenter的时候,把接口给到Presenter,比如说Presenter层获取到分类以后,通过接口更新UI即可。

    mvp.png

    优点

    剥离了View和Controller,解决了复杂的业务Activity过于庞大的问题

    缺点

    • 更新UI需要主意线程,UI控件是否已经销毁

    假如我们去请求一个数据,这个时候请求是耗时的,数据回来了,可是界面已经被用户关掉了,数据回来以后,我们得判断UI控件是否还存在。

    • 如果多个地方使用到同一个Presenter,可能会存在一些用不上的接口.

    demo

    View层

    /**
     * V层 负责交互、显示
     */
    class RegisterActivity : AppCompatActivity(), View.OnClickListener {
        private lateinit var phoneET: EditText
        private lateinit var pwdET: EditText
        private lateinit var registerBtn: Button
    
        //持有presenter层
        private lateinit var mPresenter: RegisterPresenter
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_register)
    
            mPresenter = RegisterPresenter(this)
            phoneET = findViewById(R.id.phoneET)
            pwdET = findViewById(R.id.pwdET)
            registerBtn = findViewById(R.id.registerBtn)
            registerBtn.setOnClickListener(this)
        }
    
        override fun onClick(v: View) {
            if (v.id == R.id.registerBtn) {
                //通过中间层 请求数据
                mPresenter.regist(
                    phoneET.text.toString(),
                    pwdET.text.toString()
                )
            }
        }
    
        fun showMessage(message:String){
            Toast.makeText(this, "$message", Toast.LENGTH_SHORT).show()
        }
    
    }
    

    presenter 层

    /**
     * 中间层-
     * 1、抽离Ativity中的逻辑代码
     * 2、请求数据
     */
    class RegisterPresenter {
        //持有model层
        private lateinit var mRegisterModel: RegisterModel
        private lateinit var mActivity: RegisterActivity
        //持有View层 一般用接口
        constructor(activity: RegisterActivity){
            mActivity = activity
            mRegisterModel = RegisterModel()
        }
        fun regist(phone:String,pwd:String) {
            MainScope().launch {
                mRegisterModel.regist(phone,pwd){
                    //更新UI
                    if(it){
                        mActivity.showMessage("登录成功")
                    }else{
                        mActivity.showMessage("登录失败")
                    }
                }
            }
    
        }
    
    }
    

    Model层

    /**
     * 数据层 - 请求数据
     * 1.数据库
     * 2.网络
     * 3.其他app
     */
    class RegisterModel {
        //不需要持有view、presenter层  通过回调将数据传给presenter层
        suspend fun regist(phone: String, pwd: String,response:(Boolean)->Unit) {
                delay(2000)
                response.invoke(Random.nextBoolean())
        }
    }
    

    相关文章

      网友评论

          本文标题:MVP基础篇

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