Comprensión y optimización de la arquitectura de la aplicación MVP

Arquitectura MVP

La arquitectura MVP se desarrolla a partir de MVC. En MVP, M significa Modelo, V significa Vista y P significa Presentador.

  • El modelo es responsable de obtener los datos, la fuente de los datos puede ser la red o la base de datos local, etc .;
  • View es responsable de mostrar los datos de la interfaz e interactuar con los usuarios;
  • Presenter es el puente de comunicación entre Model y View. Separa Model y View y también es el lugar donde se realizan los negocios;

La relación entre estos tres niveles es la siguiente:
Diagrama de arquitectura de la aplicación MVP

Expliquemos brevemente con un pequeño proceso simple: el
usuario toca la interfaz para activar un evento, la capa de Vista notifica a la capa de Presentador del evento, la capa de Presentador notifica a la capa de Modelo para procesar el evento, la capa de Modelo envía el resultado a la capa de Presentador después del procesamiento, y luego la capa de Presentador. Notifique a la capa Ver, y finalmente la capa Ver realiza cambios. Este es un conjunto completo de procesos.

Ejemplo de MVP

Para ilustrar mejor el MVP, simplemente citamos un ejemplo de MVP.

Capa de modelo

La capa Modelo es en realidad la capa de datos. Esta capa puede obtener contenido en formato binario o JSON de la red, la base de datos o el sistema de archivos, y cuando los datos se pasan a la capa Presenter, deben analizarse en JavaBeans.

JavaBean
public class UserBean {
     private String mFirstName;
     private String mLastName;
     public UserBean(String firstName, String lastName) {
            this. mFirstName = firstName;
            this. mLastName = lastName;
     }
     public String getFirstName() {
            return mFirstName;
     }
     public String getLastName() {
            return mLastName;
     }
}

Modelo

El modelo se ocupa principalmente de la lectura y escritura de datos y la conversión entre JavaBeans y datos nativos. Defina la interfaz de la siguiente manera:

public interface IUserModel {
    void setID(int id);
    void setFirstName(String firstName);
    void setLastName(String lastName);
    int getID();
    UserBean load(int id);		// 通过id读取user信息,返回一个UserBean
}

Capa de presentador

Esta capa es donde se encuentra el código principal para el procesamiento de la función.En general, hay muchas funciones en una aplicación, y cada función debe tener un presentador para manejar sus funciones.

public class UserPresenter {
     private IUserView mUserView;			//注意此处对 View 层的引用
     private IUserModel mUserModel;			//对 Model 层的引用

     public UserPresenter(IUserView view) {
            mUserView = view;
            mUserModel = new UserModel();
     }

     public void saveUser( int id, String firstName, String lastName) {
            mUserModel.setID(id);
            mUserModel.setFirstName(firstName);
            mUserModel.setLastName(lastName);
     }

     public void loadUser( int id) {
           UserBean user = mUserModel.load(id);
            mUserView.setFirstName(user.getFirstName()); // 通过调用IUserView的方法来更新显示
            mUserView.setLastName(user.getLastName());
     }
}

Para la capa Presenter, en circunstancias normales también habrá interfaces para estandarizar sus funciones.

public interface UserPresenterI {
     public void saveUser( int id, String firstName, String lastName)
     public void loadUser( int id) 
}

Ver capa

La capa Ver se utiliza para mostrar la interfaz al usuario. En primer lugar, debemos usar la especificación de la interfaz para la capa Ver:

public interface IUserView {
     int getID();
     String getFristName();
     String getLastName();
     void setFirstName(String firstName);
     void setLastName(String lastName);
}

La clase de implementación es generalmente Actividad o Fragmento:

public class MainActivity extends Activity implements OnClickListener,IUserView {

     UserPresenterI presenter;
     EditText id,first,last;
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout. activity_main);

            findViewById(R.id. save).setOnClickListener( this);
            findViewById(R.id. load).setOnClickListener( this);
            id = (EditText) findViewById(R.id. id);
            first = (EditText) findViewById(R.id. first);
            last = (EditText) findViewById(R.id. last);

            presenter = new UserPresenter(this);		//注意此处对 Presenter 的引用
     }

     @Override
     public void onClick(View v) {
            switch (v.getId()) {
            case R.id. save:
                 presenter.saveUser(getID(), getFristName(), getLastName());
                 break;
            case R.id. load:
                 presenter.loadUser(getID());
                 break;
            default:
                 break;
           }
     }

     @Override
     public int getID() {
            return new Integer( id.getText().toString());
     }

     @Override
     public String getFristName() {
            return first.getText().toString();
     }

     @Override
     public String getLastName() {
            return last.getText().toString();
     }

     @Override
     public void setFirstName(String firstName) {
            first.setText(firstName);
     }

     @Override
     public void setLastName(String lastName) {
            last.setText(lastName);
     }
}

De esta manera, la capa Ver solo procesa el contenido de la interfaz. Para una lógica empresarial específica, debido a que la capa Ver hace referencia a la interfaz de Presenter, se puede llamar al método Presenter. La interfaz de la capa de vista también se hace referencia en la implementación de Presenter, por lo que el método de la interfaz de vista se puede llamar directamente en el negocio o devolver la llamada para cambiar la interfaz.

Ventajas y desventajas de la arquitectura MVP

Las ventajas de MVP se pueden resumir en el ejemplo anterior:

  1. Coloque una gran cantidad de código comercial en Presenter, lo que reduce en gran medida la complejidad de la actividad.
  2. Datos ocultos, los datos son procesados ​​por la capa Modelo, que es completamente transparente para la capa Vista;
  3. Presenter se puede reutilizar y un presentador se puede usar para múltiples vistas.
  4. División obvia de las responsabilidades del módulo y niveles claros;

Pero al mismo tiempo, este modelo de MVP también traerá muchas deficiencias, de las cuales la grande es

  • La legibilidad del código es deficiente, lo que aumenta los costos de mantenimiento de la aplicación
  • Aumente enormemente la cantidad de archivos de interfaz

Por ejemplo, cuando necesito modificar una función, primero encuentro la ubicación del problema en la interfaz y luego veo el código ejecutado en el método ejecutado, pero en la estructura MVP, la capa Ver solo guarda el Presentador Interfaz, si hace clic en algunos métodos directamente, seguirá en el archivo de interfaz de Presenter. Si hay varias clases de implementación en este momento, será muy problemático. Debe encontrar la clase de implementación de Presenter en Vista. Esto aumentará el costo de mantenimiento del código utilizando la arquitectura MVP.

Otra cosa a tener en cuenta es que en el modelo MVP, las capas de Vista y Presentador se refieren a la clase base de cada una o a sí misma, y ​​se llamarán a los métodos de la otra cuando sea necesario. Aunque esto también puede aislar las dos capas, dicho aislamiento depende completamente de la interfaz, lo que aumentará en gran medida la cantidad de archivos de interfaz. En el caso del desarrollo real, no todas las funciones necesitan ser lo suficientemente complicadas como para ser definidas usando una interfaz. El aumento de interfaces aumentará el costo de mantenimiento del programa. Por ejemplo, es fácil seguir el archivo de interfaz cuando se sigue el código, pero es difícil encontrar el código de implementación de la función específica.

Mejorar

Lo primero a destacar es que se debe mantener el principio de separación de View y Presenter, y sobre esta base, mientras se reduzca la definición de la interfaz y las referencias entre ambas partes, se puede reducir el costo de mantenimiento. Entonces, en este caso, la arquitectura MVP se volverá así:
Arquitectura MVP mejorada

Para el modo MVP, debido a que muchas funciones de Presenter necesitan activar cambios en la interfaz, contiene una interfaz de capa de vista, y este método se llama cuando es necesario. Es precisamente por la complejidad del código MVP que esta referencia aumenta. Por lo tanto, para resolver este problema, Presenter debe abandonar su dependencia de la interfaz de Vista, por lo que solo se ocupa de la lógica empresarial y se separa completamente de las operaciones en la interfaz.

Es decir, en el diagrama de estructura MVP anterior, la referencia bidireccional entre View y Presenter debe cambiarse a una referencia unidireccional. La capa de Vista contiene una referencia a Presentador y viceversa. Esto también hace que la definición de la interfaz de Vista sea innecesaria, y si Presenter necesita usar la interfaz es completamente independiente de la estructura del código, por lo que esto reducirá la cantidad de archivos de interfaz en este modo.

No solo eso, después de la mejora, también permite que el presentador se concentre completamente en la lógica empresarial, de lo contrario, el presentador debe llamar a qué método de vista y cuándo. Utilice abstraído

Problema tras mejora

Después de hacer esto, dado que no hay ninguna referencia a la Vista, se convierte en un problema que se debe notificar a la interfaz cuando es necesario cambiarla. Hay dos formas de solucionarlo:

  • Utilice setListener para configurar el oyente en el presentador. Cuando la lógica necesite que la interfaz cambie, se llamará a la interfaz en el oyente
  • Cuando la capa Ver llama al método Presenter, pasa a una interfaz de devolución de llamada para manejar posibles cambios futuros de la interfaz.
Ejemplo

Después de usar el método anterior, todas las funciones del modo MVP se pueden completar sin hacer referencia a la interfaz de visualización. De hecho, usar Listener es similar a usar la interfaz de View, pero esta situación será más general, por lo que Presenter puede trabajar sin depender de View:

public class UserPresenter {

     private XListener listener;
     private IUserModel mUserModel;			//对 Model 层的引用

     public UserPresenter(IUserView view) {
            mUserView = view;
            mUserModel = new UserModel();
     }

     public void saveUser( int id, String firstName, String lastName) {
            mUserModel.setID(id);
            mUserModel.setFirstName(firstName);
            mUserModel.setLastName(lastName);
     }

     public void loadUser( int id) {
            UserBean user = mUserModel.load(id);
            listener.onUserGot(user);		//使用 Listener 来替代 IView
     }

    public void loadUser(int id, XListener onLoadListener) {
            UserBean user = mUserModel.load(id);
            onLoadListener.onUserGot(user);		//使用方法上的实参来替代 IView
    }

     public interface XListener {
     	   void onUserGot(User user)
     }
}

Estructura de código

Después de usar el modelo MVP mejorado, el código se convertirá en un modelo basado en funciones. Para la estructura del paquete, se pueden usar las siguientes soluciones:

  • src
    • Herramientas generales
      • Biblioteca base de red
      • análisis de los datos
      • ...
    • Componentes de UI universal
      • Vista personalizada de uso común
      • Componentes de interfaz de uso común
      • ...
    • Función uno
      • modelo
        • javabean
      • presentador
      • ver
        • actividad
        • fragmento
        • ver
        • ...
    • Función dos
      • modelo
      • presentador
      • ver
    • ...

Supongo que te gusta

Origin blog.csdn.net/Lee_Swifter/article/details/104717081
Recomendado
Clasificación