Kotlin之框架模式MVP总结和测试代码

一、MVP框架设计模式基本认识
   (一) 基本概念
MVP模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块
   1.模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;
   2.视图(View):负责界面数据的展示,与用户进行交互;
   3.主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来

MVP模式的整个核心过程
在这里插入图片描述
   (二)开发中MVP框架模式的设计
1.一般MVP设计都是新建一个mvp的包名,里面分别在建model、view、presenter包名,mvp包名和页面的包名ui的activity和fragment是分开的

mvp放到activity包名下就显得很难看

2.mvp包下的文件设计
   (1) model包名下的类
设计数据处理的逻辑,这里一般还设计一个内部接口类,让presenter对象可以设置监听并得到数据。因为好多数据处理都是需要子线程的,不能马上就返回数据

   (2) view包名下的类
设计视图中需要的逻辑,都是接口方法,该类也是接口类。这个接口类也是需要固定的Activity页面来实现,并重写里面的方法,在方法里面写入页面的操作,这些重写方法能否得到回调都是Presenter对象来控制的,一般都是数据或逻辑处理完后再判断相应的方法回调

   (3) presenter包名下的类
设计activity和model的交互,既要有View对象,也要有model对象
Activity中把数据相关的逻辑操作都扔给了Presenter去做,View只负责处理与用户界面操作。而Presenter调用Model处理完数据之后,再通过View接口方法更新View显示的信息

二.下面看下MVP模式在具体项目中的使用
登录页面:

点击登录并验证成功后跳转到用户界面

   (一) 详细设计过程和思路
1.写布局页面,两个EditText和一个按钮
2.设计用户的基数User,设置用户名和密码的get和set方法
3.设计mvp中的View接口类LoginView,接口里面定义方法:获得用户的账号、获得用户的密码、登录、显示网络异常、登录验证错误这五个方法
代码:

/**
 * mvp中的View的定义
 * 用户登录界面用户的操作行为的定义
 */
interface LoginView {
    
    
    fun getAccount(): String//获取用户的账号,返回账号
    fun getPassword(): String//获取用户的莫玛,返回密码
    fun loginSuccess(user: User) //登录的实现,需要传入用户对象
    fun showNetworkError() //显示网络异常
    fun showVerifyFailed() //信息验证失败,账号或密码有误
}

4.设计mvp中的model类LoginModel,这个类需要验证用户的账号和密码是否正确。并创建一个内部接口,让数据处理完成后返回时间,因为一般网络数据都是在子线程中完成,不能马上返回数据

/**
 * MVP中的model数据处理类
 * 这里处理登录时的数据
 */
class LoginModel {
    
    
    /**
     * 处理登录业务并返回结果
     */
    fun login(name: String, password: String, onLoginResultListener: OnLoginResultListener) {
    
    
        //一般登录都是请求服务器,验证
        //这里就简单一点,大家别介意
        if ("liwen" == name && "123456" == password) {
    
    
            onLoginResultListener.loginSuccess(User(name, password)) //登录成功,给他返回用户对象
        } else {
    
    
            onLoginResultListener.loginFailure() //登录失败
        }
    }

    //回调接口
    interface OnLoginResultListener {
    
    
        fun loginSuccess(user: User) //登录成功后回调的方法,返回User对象
        fun loginFailure() //登录失败后回掉的方法
    }
}

5.设计mvp中的Presenter类LoginPresenter,实现View和Model的交换,重点理解

/**
 * mvp中Presenter中的设计
 * 也是比较难,需要重点理解的一个
 * presenter是主持人的意思,view和model的中间者
 * 需要同时要有View的对象和Model的对象!一般做法是:在构造方法中创建model对象,并创建一个方法绑定View接口
 * 这里可以发现数据处理后或者逻辑判断完后都是给mvp中的View对象来做操作的!
 */
class LoginPresenter {
    
    
    /**
     * 登录业务实现者,数据处理的操作者
     */
    private val mLoginModel: LoginModel

    /**
     * 在构造方法中实例化model对象
     */
    init {
    
    
        mLoginModel = LoginModel()
    }

    //视图接口对象
    private lateinit var mLoginView: LoginView

    /**
     * 绑定View 的方法
     *
     * @param loginView
     */
    fun bind(loginView: MyActivity) {
    
    
        mLoginView = loginView
    }

    /**
     * 登录业务
     */
    fun login() {
    
    
        val account: String = mLoginView!!.getAccount().toString()
        val password: String = mLoginView!!.getPassword().toString()
        Log.e("TAG", "account:$account,password$password")
        if (checkParameter(account, password)) {
    
    
            doSomePrepare()
            //登录 ,需要处理数据,所有要在model中执行
            mLoginModel.login(account, password, object : OnLoginResultListener {
    
    
                //登录成功的回调方法
                override fun loginSuccess(user: User) {
    
    
                    mLoginView!!.loginSuccess(user) //在给视图页面返回User对象
                }

                //登录失败的回调方法
                override fun loginFailure() {
    
    
                    mLoginView!!.showVerifyFailed() //在给视图页面返回验证失败的结果
                }
            })
        }
    }

    /**
     * 做一些准备
     */
    private fun doSomePrepare() {
    
    
        //这里可以设置按钮不可点击!否则一直点击登录也是不好
    }

    /**
     * 检测参数是否是否为空~~~
     *
     * @param account
     * @param password
     * @return
     */
    private fun checkParameter(account: String, password: String): Boolean {
    
    
        if (TextUtils.isEmpty(account) or TextUtils.isEmpty(password)) {
    
    
            mLoginView!!.showVerifyFailed() //提示错误
            return false
        } else if (!checkNetwork()) {
    
    
            mLoginView!!.showNetworkError() //提示网络错误
            return false
        }
        return true
    }

    /**
     * 检测网络是否可用
     */
    fun checkNetwork(): Boolean {
    
    
        return true //先显示可以联网,实际中要用代码判断
    }
}

上面有些方法是可以不写的,比如检查网络或做一些准备,但是实际程序中,是要做很多判断的,这里就随便啰嗦几句
6.主活动Activity,重点理解

/**
 * 登录程序示例的Activity
 * 这里需要创建presenter对象,presenter对象中是有view对象和model对象的!
 */
class MyActivity : AppCompatActivity(), LoginView, OnClickListener {
    
    

    private lateinit var loginPresenter: LoginPresenter

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
    }

    /**
     * 初始化数据
     */
    private fun initView() {
    
    
        btn_login.setOnClickListener(this)
        loginPresenter = LoginPresenter()
        //绑定View和Presenter,因为这个Activity已经实现了接口,已经包含了View对象
        loginPresenter.bind(this)
    }

    /**
     * 登录按钮的监听方法
     * 这里要做后台数据的处理,需要用到Presenter
     */
    override fun onClick(v: View) {
    
    
        if (v.id == R.id.btn_login) {
    
    
            loginPresenter.login()
        }
    }

    /**
     * 下面五个方法都是实现LoginView后要是实现的方法
     */
    override fun getAccount(): String {
    
    
        return et_name.text.toString()
    }

    override fun getPassword(): String {
    
    
        return et_password.text.toString()
    }

    override fun loginSuccess(user: User) {
    
    
        //登录成功后,一般是实现页面的跳转
        Toast.makeText(this@MyActivity, user.name + "登录成功", Toast.LENGTH_SHORT).show();
        //页面跳转
        val intent = Intent(this@MyActivity, UserInfoActivity::class.java)
        intent.putExtra("user", user)
        startActivity(intent)
    }

    override fun showNetworkError() {
    
    
        Toast.makeText(this, "当前网络不可用", Toast.LENGTH_SHORT).show()
    }

    override fun showVerifyFailed() {
    
    
        Toast.makeText(this, "输入的用户名或密码有误", Toast.LENGTH_SHORT).show()
    }
}

上面可以看到在初始化时就创建loginPresenter对象,而loginPresenter的构造方法中也是创建了loginModel对象,Activity实现了LoginView,就相当于有了LoginView对象,这是只需要用loginPresenter绑定LoginView,这时MVP的model、view、presenter三者都已经实例化,并关联在一起了
上面语句loginPresenter绑定LoginView的是:loginPresenter.bind(this);绑定Avtivity,也是绑定View!loginPresenter中调用LoginView的方法都是在Activity中执行的
程序运行后的显示:

下载源码github地址:loginMVP(kotlin),没学过kotlin先看一下java代码:loginMVP(java)

猜你喜欢

转载自blog.csdn.net/qq_35091074/article/details/123228774