美文网首页
Android开发-MVP框架学习记录

Android开发-MVP框架学习记录

作者: lyichao | 来源:发表于2019-01-22 15:27 被阅读0次

    前言

    MVP架构流行已久,但由于实在没时间(太懒),所以一直对MVP停留在听说一词上。

    由于最近公司让我接收一个android项目,而该项目之前的android版本就是使用MVP架构,因此得以真正接触到了MVP架构。

    本文章Demo点击下载

    首先,我们来理解下MVP是什么?

    MVP全称Model-View-Presenter,它把项目大概划分为3个模块,其实分别对应:

    M层:实体层,负责获取实体数据。

    V层:视图层,对应XML文件与Activity/Fragment

    P层:逻辑控制层,同时持有ViewModel对象。

    MVP的流程图大致如下所示:

    那么,MVP有什么优势?

    1. 把业务逻辑抽离到Presenter层中,View层专注于UI的处理。

    2. 分离视图逻辑与业务逻辑,达到解耦的目的。

    3. Presenter被抽象成接口,可以根据Presenter的实现方式进行单元测试。

    4. 提高代码的阅读性。

    5. 可拓展性强。

    同样,有优势就有缺点!

    1. 项目结构会对后期的开发和维护有一定影响,具体视APP的体量而定。

    2. 代码量会增多,如何避免编写过多功能相似的重复代码是使用MVP开发的一个重要处理问题。

    3. 有一定的学习成本。

    趁热打铁,撸起袖子就是干!

    下面通过输入账号密码实现登录的例子,来看看MVP到底是如何分工(甩锅)合作的。

    创建一个空项目,名为MVPDemo好了。然后在项目下的mvpdemo文件夹中新增modelviewpresenter三个文件夹,分别对应实体层、视图层、逻辑控制层。然后在view文件夹中创建activity文件夹,并把MainActivity拖至其中。如下图所示:

    activity_main.xml中添加三个组件,用于输入账号密码和登录

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".view.activity.MainActivity">
    
        <EditText
            android:id="@+id/uid"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="157dp"
            android:ems="10"
            android:hint="账号"
            android:inputType="textPersonName"
             />
    
        <EditText
            android:id="@+id/pwd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="219dp"
            android:ems="10"
            android:hint="密码"
            android:inputType="textPassword" />
    
        <Button
            android:id="@+id/login"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="128dp"
            android:text="登录" />
    

    回到MainActivity中,绑定三个UI组件

    public class MainActivity extends AppCompatActivity {
    
        private EditText mUid,mPwd;
        private Button mLogin;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initUI();       //初始化UI
            initListener(); //初始化监听事件
        }
    
        private void initUI() {
            mUid.findViewById(R.id.uid);
            mPwd.findViewById(R.id.pwd);
            mLogin.findViewById(R.id.login);
        }
    
        private void initListener() {
            mLogin.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                }
            });
        }
    }
    

    接下来就算是开始用到MVP了,先来分析下登录操作,因为输入账号密码后需要进行登录操作,而登录操作可以看作有那么几步:

    1.登录验证失败:账号密码不能为空,账号密码不能错误。如果存在这两种情况,则弹出对应Toast

    2登录验证成功:弹出登录成功Toast,并跳转到登录成功页面

    因此登录操作中既包括了逻辑控制层操作,也包括了视图层操作

    那么我们就需要创建对应的文件

    1.在presenter文件夹下创建接口类LoginActivityPresenterimpl文件夹;

    2.在LoginActivityPresenter接口中新建一个登录方法;

    3.接着在impl文件夹内创建LoginPresenterImpl类并实现LoginActivityPresenter接口的登录方法;

    // 2.
    package com.example.lee.mvpdemo.presenter;
    public interface LoginActivityPresenter {
        void login(String uid, String pwd);
    }
    
    // 3.
    package com.example.lee.mvpdemo.presenter.impl;
    import com.example.lee.mvpdemo.presenter.LoginActivityPresenter;
    public class LoginPresenterImpl implements LoginActivityPresenter {
        @Override
        public void login(String uid, String pwd) {
        }
    }
    
    

    LoginPresenterImpl中的完善login方法,其中,因为需要在验证操作后通知UI层弹出Toast操作,所以需要引入视图层的方法。所以在完善login方法前,先来添加视图层需要的方法:

    1.在view文件夹下创建iView文件夹

    2.在iView文件夹新建一个接口类ILoginActivity

    3.在接口类ILoginActivity中添加两个方法,一个用于验证成功后返回,一个用于验证失败后返回

    // 3.
    package com.example.lee.mvpdemo.view.iView;
    public interface ILoginActivity {
        //用于验证成功后返回
        void loginSuccess(int resultCode, String msg);
        //用于验证成失败后返回
        void loginFailed(int resultCode, String msg);
    }
    

    万事俱备,只欠login。我们回到LoginPresenterImpl类,往里面引入刚刚添加的接口类ILoginActivity,并完善登录验证失败/成功时的代码

    package com.example.lee.mvpdemo.presenter.impl;
    import android.text.TextUtils;
    import com.example.lee.mvpdemo.presenter.LoginActivityPresenter;
    import com.example.lee.mvpdemo.view.iView.ILoginActivity;
    public class LoginPresenterImpl implements LoginActivityPresenter {
        
        private ILoginActivity mIView;
        public  LoginPresenterImpl(ILoginActivity iLoginActivity){
            mIView = iLoginActivity;
        }
        @Override
        public void login(String uid, String pwd) {
            System.out.println("触发:login"+" "+"uid:"+uid+" "+"pwd:"+pwd);
            if(TextUtils.isEmpty(uid)){
                //此时账号为空,告诉视图层需要展示调取loginFailed方法
                mIView.loginFailed(0,"账号不能为空");
            }else if(TextUtils.isEmpty(pwd)){
                //此时密码为空,告诉视图层需要展示调取loginFailed方法
                mIView.loginFailed(0,"密码不能为空");
            }else if(uid.equals("chaoiscool")  && pwd.equals("123456")){
                //此时验证成功,告诉视图层需要展示调取loginSuccess方法;
                //如果有保存用户信息的需要,也可以在此处告诉实体层,让它去进行保存用户信息,
                //操作和第6步似,例如:
                //mModel.saveUserBean(userBean)
                mIView.loginSuccess(1,"登录成功");
            }else {
                //此时账号或者密码错误,告诉视图层需要展示调取loginFailed方法
                mIView.loginFailed(1,"登录失败");
            }
        }
    }
    

    现在基本的设置已经完成,我们把注意力移到MainActivity身上,此时的MainActivity还是独自一人,还没和逻辑控制层、实体层和视图层建立联系。因此我们来给他们搭建一座桥梁:

    1.引入逻辑控制层LoginPresenterImpl

    private LoginPresenterImpl mLoginPresenter;
    

    2.为LoginPresenterImpl新建实例对象

    private LoginActivityPresenter getPresenter(){
       if(null == mLoginPresenter){
           mLoginPresenter = new LoginPresenterImpl(this);
       }
       return mLoginPresenter;
    }
    

    3.触发登录事件时,调用LoginPresenterImpl(逻辑控制层)里的login方法

    private void initListener() {
        mLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.println("触发:onClick");
                getPresenter().login(mUid.getText().toString(),mPwd.getText().toString());
            }
        });
    }
    

    4.实现接口类ILoginActivity(视图层)的两个方法,并在各自的中实现对应的逻辑

    public class MainActivity extends Activity implements ILoginActivity
    
    //登录成功回调
    @Override
    public void loginSuccess(int resultCode, final String msg) {
        System.out.println("触发:loginSuccess");
        System.out.println("触发:msg:"+msg);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(!TextUtils.isEmpty(msg)){
                    Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
    
    //登录失败回调
    @Override
    public void loginFailed(int resultCode, final String msg) {
        System.out.println("触发:loginFailed");
        System.out.println("触发:msg:"+msg);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(!TextUtils.isEmpty(msg)){
                    Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
    

    5.同样的,如果有保存用户数据的需要,也需要实现前面3、4的操作

    总结

    到这里为止,MVP的分工合作就已经配置完成。现在也应该对MVP的操作有一定程度的了解了。其

    核心是逻辑控制层,所有的UI操作和数据操作,都是经过逻辑控制层来分派的。它的存在就像是你的BOSS,分派不同的任务给下属,专业的事情由专业的人来干!

    最后放上效果图:

    相关文章

      网友评论

          本文标题:Android开发-MVP框架学习记录

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