¿Cómo debo pasar los datos (por ejemplo, qué elemento se hizo clic) entre Actividades en MVP?

Tengo la lista de artículos mostrados con el patrón MVP. La vista es una actividad (también conocida como ItemsList). Quiero mostrar la siguiente actividad (también MVP'ed, aka ItemDetails) con detalles del elemento pulsado en ItemsListActivity.

El modelo para ItemsList se alimenta con los datos del repositorio. Así que en realidad es RMVP. Se parece a esto:

|->Model<->Presenter<->View [ItemsList] Repository<-| |->Model<->Presenter<->View [ItemDetails] 

Así que el modelo de ItemsList ya sabe exactamente qué elemento del modelo se ha hecho clic para poder pasarlo de inmediato desde ItemsList a ItemDetails sin recuperar datos del repositorio de nuevo / mapeo de datos a modelo / hacer nuevo modelo para ItemDetails etc.

¿Cómo debo pasar los datos (por ejemplo, qué elemento se hizo clic) entre Actividades en MVP?

Solución 1

Pasar esos datos con intención ( similar a lo que se discute aquí ), pero … ¿qué hacer con esos datos? Descomprimirlo desde Intent en Activity (View) mientras debería tenerlo en el otro lado de MVP, es decir, en Model. ¿Se pasa de Ver a través de presentador a modelo?

Pero a continuación, Modelo en ItemDetails no se crea desde el "lado negativo de MVP" (desde Repositorio), sino desde "upperside de MVP" (desde Presenter).

Solución 2

Pase sólo el ID del elemento seleccionado a ItemDetails View (similar a lo que android10 / Android-CleanArchitecture propone en UserDetailsActivity con el campo private int userId , esto es también lo que googlecodelabs 'NoteDetailPresenter utiliza)

Sin embargo, puede haber un problema porque puedo tener dos implementaciones de repositorio:

  • Uno con el escondrijo y después puedo pasar el ID del artículo chascado a la vista de ItemDetails (sin embargo parece ser over-engineered), similar a lo que android10 / Android-CleanArchitecture propone en UserDetailsActivity con el campo private int userId;
  • Segundo sin caché y luego ni siquiera puedo pedir ID porque no tengo acceso a la lista de fetched para ItemsList

Creo que los dos escenarios son válidos, puedes manejarlos con un flujo como este:

  • La vista de lista pasará la vista de detalles, ya sea el ID o el elemento en sí.
  • Su presentador se inicializará con una instancia de la vista (en este caso será la actividad).
  • Durante la inicialización del presentador, puede comprobar si su vista tiene un elemento adicional (en la intención de la actividad extra). Luego extraerlo y usarlo para mostrar la información de la vista.
  • Si el extra de la vista tiene el id del elemento, el presentador obtendrá el id y lo usará para recuperar los detalles del repositorio.

Algo como esto:

 public class DetailsPresenter { public DetailsPresenter(DetailsActivity activity) { if(activity.getIntent().getExtras!=null) { if(activity.getIntent().getExtras().containsKey(ITEM_ID_KEY)) { //get the item id int itemId=activity.getIntent().getExtras().getInt(ITEM_ID_KEY); //TODO retrieve the item details from the repository }else if(activity.getIntent().getExtras().containsKey(ITEM_KEY)) { //get the item Item item=activity.getIntent().getExtras().getParcelable(ITEM_KEY); //TODO update the view with item details } } } 

Su DetailsActivity puede ser como esto:

 public DetailsActivity extends Activity{ private DetailsPresenter mDetailsPresenter; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_details); //initialize the presenter mDetailsPresenter=new DetailsPresenter(this); } } 

Recientemente, también he utilizado MVP en mi aplicación. He encontrado el mismo problema y pasar los datos de ItemListActivity a ItemDetailActivity con la intención. Pasé la clase del modelo que implementa la interfaz Parcelable y no encontré ningún problema, funciona bien.

La razón es: En ItemDetailActivity, tenemos que buscar los datos de la base de datos o del repositorio en su caso, lo que aumenta una operación en su aplicación.

En ItemlistActivity usted realizará solamente una sola operación para obtener todos los datos. Si bien, si pasa los datos de ItemListActivity a ItemDetailActivity, sólo tiene que obtener datos en ItemDetailActivity sin ninguna operación especial.

Le sugiero que vaya para la Solución 1.

En una aplicación he utilizado ambos métodos y una tercera opción. En la tercera opción utilizo una caché de nivel de aplicación y rellenar el objeto allí y pasar la clave de caché a la nueva intención. Esta es una variación de la solución 2 sin el caché de repo. Sé que necesitaré solamente el artículo en la memoria temporalmente; Por lo tanto, es muy importante quitar el elemento de la memoria caché para evitar pérdidas de memoria. Generalmente me gusta la segunda solución ya que no tengo que hacer el objeto parcelable (tal vez un poco perezoso). No noté diferencias de rendimiento de ninguno de los métodos.

Al final, me instalé en la solución 1 al pasar modelos de vista (tengo todos mis modelos de vista parcelable). Solución 2 cuando se utilizan modelos domian (ya que ya están en la base de datos, es más fácil pasar una clave alrededor). Solución 2 con caché si el objeto domian está en un estado transitorio (ya sea un nuevo objeto de dominio aún no persistió o un objeto de dominio donde el estado podría ser inconsistente con la base de datos, es decir, cambios aún no persistidos y la actividad suspendida por alguna razón)

Si está utilizando la navegación de vista previa, creo que puede crear su propio paquete de capa de presentador (o algo así) y enviarlo con intención a la nueva Actividad. Entonces la nueva Actividad extraerá este paquete y lo pasará al presentador.

Las principales características del diseño MVP son:

 **MVP Pattern** View is more loosely coupled to the model. The presenter is responsible for binding the model to the view. Easier to unit test because interaction with the view is through an interface. Usually view to presenter map one to one. Complex views may have multi presenters. 

Así que le sugiero pasar modelo del elemento a su DetailsActivity donde se puede utilizar el modelo. El modelo entonces tiene que implementar una interfaz parcelable.

Además, creo que hay una tercera consideración – en MVP, usted está Model está modelando el dominio del problema y debe ser capaz de existir independientemente de la V y P elegidos. Si su ItemDetails y ItemList son parte del mismo dominio de problema, es probable que su Modelo los modelen a ambos, y lo que realmente busca hacer es presentar los datos de dos formas diferentes (una como una lista, una como detalle) .

En cuyo caso, puede ser viable compartir un Modelo , y simplemente tener diferentes capas de presentación y visualización. En cuyo caso, una vez que su detalle se ha pasado de nuevo a usted Modelo, es sólo un caso de adjuntar a un nuevo presentador para presentar el ItemDetail elegido.

Cuando se hace clic en un elemento, debe pasar esa información hasta el presentador que decidirá qué datos se deben enviar a qué actividad. A continuación, su presentador puede empaquetar los datos y la clase de actividad objetivo en una intención y pasar de nuevo a la vista original. Por ejemplo, algo como navigateToActivity (Intent i). La vista original inicia la actividad con la intención que se da. Esto permite que la vista de origen sea muda acerca de lo que debe ser la siguiente pantalla (ya que puede haber varias opciones). La lógica del negocio es el trabajo del presentador.

Entonces, el presentador de la nueva vista descomprime los datos enviados con la intención cuando el presentador es inicializado, como dijo Kishan. La vista de destino también es tonta en términos de saber qué hacer con los datos en la intención.

  • ¿En MVP está onClick la responsabilidad de View o Presenter?
  • Estructura del paquete de patrones de Android MVP
  • Implementación de MVP en la aplicación de Android
  • MVP de Android: ¿debe ser una actividad una vista o un presentador?
  • Realización de Interactors con Android MVP Clean Architecture
  • Cómo controlar ListView con el patrón MVP para Android
  • ¿Deberían inyectarse los presentadores (mvP) (dagger2) a las vistas en android?
  • Estructura en capas de Android clean architecture
  • ¿Cómo inicio un servicio desde mi Interactor usando el patrón MVP en android?
  • Prueba de la unidad MVP de Android: ¿debo burlar el bus de eventos?
  • Prueba instrumental de una vista en MVP
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.