• Android MVP模式就是这么回事儿


    MVP模式

    概念就不说了,大家都懂。View层通过Persenter层相互通信,避免了View中大量的业务代码,而将其提取到Model中。其实简单的来说,就是通过接口回调,把业务分离出去。提高代码的可读性和已维护性。
    直接看案例就明白了。

    案例(用户登录)

    常规的用户登录写法就是Activity(fragment)中获取用户名密码,网络请求登录接口,返回是否登录成功
    而MVP的模式就是,要把网络请求这一部分单独提取出来放到model层里面,View层也就是我们的Activity只写页面相关的操作,

    • 创建LoginModel如下:
    package com.cyq.mvppractice.model;
    
    public class LoginModel {
    
        public static boolean login(String username, String password) {
            //一般是请求网络接口咯
            //具体逻辑我就不写了,这里模拟一下,直接返回登录成功
            return true;
        }
    }
    

    很简单,就是一个常规类和常规操作而已,处理具体的登录网络请求

    • 定义一个接口LoginInterface和LoginPersenter类
      LoginInterface中又定义了两个接口,View和Persenter分别继承这两个接口,实现View和Persenter层的交互,具体如下
    package com.cyq.mvppractice.contract;
    
    public interface LoginInterface {
        /**
         * View层需要继承这个接口,通过接口方法View层获取返回结果
         */
        interface View {
            //判断是否登录成功
            void isLogin(boolean islogin);
        }
    
        /**
         * persenter需要继承的接口,通过接口方法传入View层的值
         */
        interface Persenter {
            //model层需要哪些传入数据从这个接口传入
            void goLogin(String username, String password);
        }
    }
    

    LoginPersenter.class

    package com.cyq.mvppractice.persenter;
    
    import com.cyq.mvppractice.contract.LoginInterface;
    import com.cyq.mvppractice.model.LoginModel;
    
    public class LoginPersenter implements LoginInterface.Persenter {
        //通过构造方法传入view,相当于传入了activity和fragment
        private LoginInterface.View view;
    
        public LoginPersenter(LoginInterface.View view) {
            this.view = view;
        }
    
        /**
         * 调用model层业务,最终通过view.isLogin(b),通知view层获取数据
         *
         * @param username
         * @param password
         */
        @Override
        public void goLogin(String username, String password) {
            boolean isLogin = LoginModel.login(username, password);
            //回调通知View层
            view.isLogin(isLogin);
        }
    }
    

    最后在View中继承LoginInterface.View接口,实例化LoginInterface.Persenter接口

    package com.cyq.mvppractice;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import com.cyq.mvppractice.contract.LoginInterface;
    import com.cyq.mvppractice.persenter.LoginPersenter;
    
    public class LoginActivity extends AppCompatActivity implements LoginInterface.View {
        private LoginInterface.Persenter mPersenter;
        private EditText usernameEt, passwordEt;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            mPersenter = new LoginPersenter(this);
            usernameEt = findViewById(R.id.et_username);
            passwordEt = findViewById(R.id.et_password);
            findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String usernameStr = usernameEt.getText().toString();
                    String passwordStr = passwordEt.getText().toString();
                    if ((!TextUtils.isEmpty(usernameStr)) && (!TextUtils.isEmpty(passwordStr)))
                        mPersenter.goLogin(usernameStr, passwordStr);
                    else {
                        Toast.makeText(LoginActivity.this, "请输入用户名或密码", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    
        @Override
        public void isLogin(boolean islogin) {
            if (islogin) {
                Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
            }
        }
    }
    
    • 就这么简单,把网络请求数据库操作等复杂业务单独放到model层中处理,通过接口回调获得model处理结果返回到View层,也就避免了在View层编写大量的业务逻辑了
    • Xml布局如下,就是两个Edittext和一个登陆按钮
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="20dp"
        tools:context=".LoginActivity">
    
        <EditText
            android:id="@+id/et_username"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入用户名" />
    
        <EditText
            android:id="@+id/et_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:hint="请输入密码" />
    
        <Button
            android:id="@+id/btn_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="登录" />
    </LinearLayout>
    
    • 没看懂?再认真看一遍,再写个小demo就ok了,主要是理解其思想
  • 相关阅读:
    delphi idhttpserver ajax 跨域解决方法
    【转】安卓apk反编译(三件套) (com.googlecode.d2j.DexException: not support version问题解决)
    C++ volatile的作用
    GetProcAddress函数
    c++ CArray函数
    CString中TrimLeft()与TrimRight()的用法
    使用Windows API进行串口编程
    SetCommMask
    AttachThreadInput
    关于CoInitialize和CoUninitialize调用的有关问题
  • 原文地址:https://www.cnblogs.com/chenyangqi/p/9341231.html
Copyright © 2020-2023  润新知