Marco (1): ejemplos de inicio de sesión y ejemplos oficiales de Google para explicar el modelo MVP

Introducción a este artículo

En el desarrollo de Android, después de clasificar los requisitos, lo que debe hacer no es escribir la primera línea de código de inmediato, sino diseñar primero el marco técnico de todo el proyecto. Este artículo explica principalmente el modelo MVP a través de ejemplos de inicio de sesión y Google. Ejemplos oficiales.

Tabla de contenido

  • ¿Por qué realizar el diseño del marco técnico?
  • modelo MVP
  • Ejemplo de inicio de sesión para explicar el modelo MVP
  • Los ejemplos oficiales de Google explican el modelo MVP
  • Dirección de descarga del código fuente

¿Por qué realizar el diseño del marco técnico?

  • Funcionalidad modular

    Haga que el programa sea modular, es decir: una alta agregación interna y un bajo acoplamiento entre módulos mejoran la eficiencia del desarrollo, permiten que cada módulo realice sus propias tareas y mejoran la legibilidad, escalabilidad, mantenibilidad y seguridad del código.

  • Mejorar la eficiencia del desarrollo

    Permite que varias personas desarrollen el mismo módulo de forma colaborativa. Después de diseñar la interfaz, los desarrolladores solo necesitan centrarse en un punto determinado (visualización de visualización, lógica de negocios/procesamiento de datos).

  • Mejorar la eficiencia de las pruebas

    Es conveniente para realizar pruebas. Cada módulo se puede probar individualmente. No es necesario completar todos los módulos antes de realizar la prueba.

  • Mejorar la mantenibilidad del código

    Puede localizar rápidamente a qué módulo pertenece el problema, realizar cambios y cambiar el módulo actual lo menos posible para afectar otras funciones, reducir la aparición de errores concurrentes y reducir la carga de trabajo de las pruebas.

Recuerde: no diseñe por diseñar, de lo contrario aumentará la cantidad de desarrollo.
Insertar descripción de la imagen aquí

modelo MVP

definición

MVP significa modo Modelo-Vista-Presentador, que se utiliza para el desarrollo de aplicaciones en capas.

  • Modelo (Modelo)
    El modelo es la parte de la aplicación que se utiliza para procesar la lógica de datos de la aplicación. Por lo general, el objeto del modelo es responsable de acceder a los datos y la lógica empresarial en la base de datos (por ejemplo: obtener datos de un servidor de red y procesarlos) y actualizando los controles cuando cambian los datos.

  • Ver :
    Ver es la parte de la aplicación que maneja la visualización de la interfaz, incluida la actualización y recuperación del contenido de la interfaz y el procesamiento de eventos activados por el usuario.

  • Presentador (Controlador)
    El controlador actúa sobre modelos y vistas. Controla el flujo de datos para modelar objetos y actualiza la vista cuando los datos cambian. Separa la vista del modelo.

Relación de llamada entre MVP

M llama a P, P llama a M, M devuelve el resultado a P y P devuelve el resultado a V. V no puede usar M directamente, lo que separa completamente la interfaz de la lógica empresarial o el procesamiento de datos.
Insertar descripción de la imagen aquí

Secuencia de ejecución del modo MVP

La secuencia de ejecución se explica en 3 situaciones. Consulte la figura siguiente para obtener más detalles.
Insertar descripción de la imagen aquí

Descripción del rol de MVP en el proyecto de Android

Insertar descripción de la imagen aquí

caso real

Función de inicio de sesión implementada en modo MVP

La interfaz de implementación de la función de inicio de sesión ingresa el nombre de usuario y la contraseña, luego los compara con el nombre de usuario simulado obtenido del servidor y luego devuelve el resultado del inicio de sesión a la interfaz.
La interfaz se muestra a continuación:
Insertar descripción de la imagen aquí
la relación correspondiente entre roles, clases e interfaces
Insertar descripción de la imagen aquí

código de procedimiento de llamada de función
Insertar descripción de la imagen aquí

  • Ver interfaz
public interface IUserLoginView {
    
    
     void setSuccessInfo();
     void setErrorInfo(int iErrorCode);
}
  • Ver archivo XML
<?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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="案例说明:"
        android:textColor="@android:color/holo_red_dark"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录功能的MVPDemo\n1、具体分为3层View-Presenter-Model\n2、V-P层传数据采用函数的参数传参\n3、M层模拟从网络获取数据。\n4、正确用户名和密码分别为:mvp,123456"
        android:textColor="@android:color/holo_red_dark"/>

    <EditText
        android:id="@+id/et_username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="mvp" />

    <EditText
        android:id="@+id/et_pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="123456" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Login"
        android:onClick="Login"/>
</LinearLayout>

  • Ver-Actividad
public  class LoginMVPDemoActivity extends AppCompatActivity implements IUserLoginView {
    
    
    private EditText etUserName;
    private EditText etPwd;

    IUserLoginPresenter bUserLoginPresenter = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login_mvpdemo);

        etUserName = (EditText) findViewById(R.id.et_username);
        etPwd = (EditText) findViewById(R.id.et_pwd);

        bUserLoginPresenter = new UserLoginPresenter(this);
    }

    @Override
    public void setSuccessInfo() {
    
    
        Toast.makeText(this,"登录成功!",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setErrorInfo(int iErrorCode) {
    
    
        if(iErrorCode == 1){
    
    
            Toast.makeText(this,"登录失败:用户名不存在或不正确",Toast.LENGTH_SHORT).show();
        }else if(iErrorCode == 2){
    
    
            Toast.makeText(this,"登录失败:密码不正确",Toast.LENGTH_SHORT).show();
        }

    }

    public void Login(View v){
    
    
        bUserLoginPresenter.login(etUserName.getText().toString(),
                etPwd.getText().toString());
    }
}

  • Interfaz del presentador-IUserLoginPresenter
public interface IUserLoginPresenter {
    
    
     void login(String username, String strPwd);
}
  • Interfaz del presentador-OnUserLoginListener
public interface OnUserLoginListener {
    
    
     void onUserLoginSuccess();
     void onUserLoginError(int iErrorCode);
}
  • Presentador de clase concreta.
public class UserLoginPresenter implements IUserLoginPresenter,OnUserLoginListener{
    
    
    IUserLoginMode bUserLoginMode = null;
    IUserLoginView bUserLoginView = null;
    public UserLoginPresenter(IUserLoginView bUserLoginView){
    
    
        bUserLoginMode = new UserLoginMode();
        this.bUserLoginView = bUserLoginView;
    }

    @Override
    public void onUserLoginSuccess() {
    
    
        bUserLoginView.setSuccessInfo();
    }

    @Override
    public void onUserLoginError(int iErrorCode) {
    
    
        bUserLoginView.setErrorInfo(iErrorCode);
    }

    @Override
    public void login(String username, String strPwd) {
    
    
        bUserLoginMode.handleLogin(username,strPwd,this);
    }
}
  • Interfaz del modelo
public interface IUserLoginMode {
    
    
     void handleLogin(String username, String strPwd,
                            OnUserLoginListener bOnUserLoginListener);
}
  • Clase de implementación del modelo
public class UserLoginMode implements IUserLoginMode {
    
    
    @Override
    public void handleLogin(String username, String strPwd,
                            OnUserLoginListener bOnUserLoginListener) {
    
    
        String s_username = "mvp";
        String s_strPwd ="123456";
        //用户名不存在
        if(!username.equals(s_username)){
    
    
            bOnUserLoginListener.onUserLoginError(1);
        } else if(username.equals(s_username) && s_strPwd.equals(strPwd)){
    
    
            bOnUserLoginListener.onUserLoginSuccess();
        }else if(username.equals(s_username) && !s_strPwd.equals(strPwd)){
    
    
            //密码不正确
            bOnUserLoginListener.onUserLoginError(2);
        }

    }
}

Demostración oficial de MVP de Google

La demostración oficial implementa el procesamiento del proceso de carga de datos: la interfaz muestra que los datos han comenzado a cargarse, los datos se están cargando y la carga de datos se completa y se muestra en la interfaz.
La interfaz se muestra de la siguiente manera:
Insertar descripción de la imagen aquí
La diferencia entre la demostración oficial y el caso de inicio de sesión

  • El modelo no abstrae la interfaz y la implementa directamente de manera concreta.
  • Agregue un contrato entre v y p. Las interfaces originales de v y p se clasifican en dos interfaces de contacto. Según las interfaces v y p, las interfaces v y p básicas se abstraen para reducir el acoplamiento entre v y p. . , aumentando la escalabilidad y mantenibilidad del programa.

Correspondencia entre roles, interfaces y clases
Insertar descripción de la imagen aquí
Proceso de llamada de funciones
Insertar descripción de la imagen aquí

  • Ver interfaz
public interface BaseView<T> {
    
    
    void setPresenter(T presenter);
}
  • Interfaz del presentador
public interface BasePresenter {
    
    
    void start();
}
  • Interfaz de contrato
public interface UserInfoContract {
    
    

    interface View extends BaseView<Presenter>{
    
    

        void showLoading();//展示加载框

        void dismissLoading();//取消加载框展示

        void showUserInfo(UserInfoModel userInfoModel);//将网络请求得到的用户信息回调

        String loadUserId();//假设接口请求需要一个userId
    }

    interface Presenter extends BasePresenter {
    
    
        void loadUserInfo();
    }

}
  • Ver-XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="案例说明:"
        android:textColor="@android:color/holo_red_dark"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Google官方提供的MVPDemo\n1、具体分为4View-Crontract-Presenter-Model\n2、contract层处于V层和P层中间,实现了原本在V层和P层的两个接口,V层和P层的接口是在Contract中对应接口的基础上再抽象一层,
使V层和P层的耦合性更低,灵活性更高。\n3、V-P层传参采用接口函数传参\n4、此Demo重点在于V层和P层的分离,M层的较少。"
        android:textColor="@android:color/holo_red_dark"/>

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/tv_address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</LinearLayout>

  • Ver-Actividad
public class GoogleMVPDemoActivity extends AppCompatActivity implements UserInfoContract.View {
    
    
    private TextView tv_name;
    private TextView tv_age;
    private TextView tv_address;

    private UserInfoContract.Presenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_google_mvpdemo);

        tv_name = (TextView) findViewById(R.id.tv_name);
        tv_age = (TextView) findViewById(R.id.tv_age);
        tv_address = (TextView) findViewById(R.id.tv_address);
        //通知P层要
        new UserInfoPresenter(this);
        presenter.start();
    }

    @Override
    public void showLoading() {
    
    
        Toast.makeText(this, "正在加载", Toast.LENGTH_LONG).show();
    }

    @Override
    public void dismissLoading() {
    
    
        Toast.makeText(this, "加载完成", Toast.LENGTH_LONG).show();
    }

    @Override
    public void showUserInfo(UserInfoModel userInfoModel) {
    
    
        if (userInfoModel != null) {
    
    
            tv_name.setText(userInfoModel.getName());
            tv_age.setText(String.valueOf(userInfoModel.getAge()));
            tv_address.setText(userInfoModel.getAddress());
        }
    }

    @Override
    public String loadUserId() {
    
    
        return "1000";//假设需要查询的用户信息的userId是1000
    }

    @Override
    public void setPresenter(UserInfoContract.Presenter presenter) {
    
    
        this.presenter = presenter;
    }
}
  • Presentador de clase concreta.
ublic class UserInfoPresenter implements UserInfoContract.Presenter {
    
    
    private UserInfoContract.View view;

    public UserInfoPresenter(UserInfoContract.View view) {
    
    
        this.view = view;
        view.setPresenter(this);
    }

    @Override
    public void loadUserInfo() {
    
    
        String userId = view.loadUserId();
        view.showLoading();//接口请求前显示loading
        //这里模拟接口请求回调-
        new Handler().postDelayed(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                //模拟接口返回的json,并转换为javaBean
                UserInfoModel userInfoModel = new UserInfoModel("小宝", 1, "杭州");
                view.showUserInfo(userInfoModel);
                view.dismissLoading();
            }
        }, 3000);
    }

    @Override
    public void start() {
    
    
        loadUserInfo();
    }

}
  • Modelo de clase concreta
public class UserInfoModel {
    
    
    private String name;
    private int age;
    private String address;

    public UserInfoModel(String name, int age, String address) {
    
    
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }
}

Resumir

Al analizar el código, preste atención a la retención de objetos entre los dos MVP de casos, la transferencia de objetos y la forma de transferir datos (paso de parámetros de método y paso de parámetros de método)

Dirección de descarga del caso

Dirección de descarga de MVPDemo

Link de referencia

Patrones ilustrados MVC, MVP, MVVM: ejemplos para explicar para que lo sepas claramente

Supongo que te gusta

Origin blog.csdn.net/li1500742101/article/details/105382015
Recomendado
Clasificación