Dificultades para implementar Model-View-Presenter en Android

Model-View-Presenter (MVP) es un patrón de diseño bien conocido para aplicaciones GUI. Para Android, la implementación de la lógica empresarial en un módulo Java sencillo facilita las pruebas sin requerir un emulador de Android.

Sin embargo, estoy teniendo dificultades para implementar el patrón en Android debido a requisitos especiales para la GUI de las aplicaciones de Android:

  • Una actividad puede ser destruida en cualquier momento (llamada entrante, el usuario presiona el botón de inicio, …), y cuando se recrea debe estar en el mismo estado que cuando se dejó. Esto es diferente a la mayoría de las otras aplicaciones GUI.

  • Una actividad puede atravesar muchos estados del ciclo de vida. Puede interrumpirse, en cuyo caso la UI de la Actividad no debe modificarse. Si, por ejemplo, algunos datos se están cargando en segundo plano, no se puede entregar a la parte Ver de MVP (Actividad) si se encuentra en estado de pausa. Una vez más, este es un requisito inusual.

He leído el blog MVP para Android y he mirado el ejemplo del código fuente . El objetivo final que estoy tratando de lograr utilizando el patrón MVP es poder traducir toda la lógica de negocio a Objective-C usando el transpiler j2objc , de modo que la lógica de negocio pueda reutilizarse al implementar la misma aplicación en iOS.

¿Hay alguien que ha implementado el patrón MVP para Android con éxito, y en ese caso, ¿qué me falta?

Sugiero implementar el componente MVP sin involucrar Actividad, quizás conceptualmente pensando en lo que sería útil tanto en Android como en GWT. Cree el componente utilizando el desarrollo orientado a pruebas con una interfaz de Vista simulada, agregando pruebas hasta que la lógica de negocio esté completamente implementada y verificada. TDD ayuda a mantener la API del componente (¿por qué escribir pruebas para cosas que no necesita?), Lo que facilita el portado del componente.

Los requisitos de actividad que describe pueden generalizarse para que sean independientes de la plataforma: el componente debe ser serializable (pequeño, no específicamente serialización de Java) y debe aceptar eventos del estado del ciclo de vida. Aquellos, también, pueden ser probados completamente usando simulacros para las características del sistema. Al pasar por este paso, es probable que note que pocos de los requisitos de la actividad son necesariamente específicos de Android, y puede ser útil en otras plataformas. Evite crear APIs de servicio enormes; Para soportar la serialización, por ejemplo, todo lo que se necesita son métodos de almacenamiento / carga, no algo así como la Parcel API . He encontrado describiendo tales API de servicio a otro desarrollador en una pizarra para ser una gran manera de encontrar pelusa innecesaria.

A continuación, transfiera el componente a Android, tal vez creando una actividad que delega en el componente y proporciona clases de implementación específicas de Android para las interfaces simuladas. Todo debería "funcionar" la primera vez, pero en realidad, algunos requisitos pueden haber sido perdidos, por lo que agregar a la parte independiente de la plataforma y repetir.

Cuando estés listo para portar a iOS, vuelve a implementar las interfaces simuladas anteriormente. Si estas interfaces son magra, probablemente será más fácil crearlas directamente en Objective-C, importando los encabezados de protocolo generados por j2objc. Por ejemplo, la clase NSDictionaryMap de j2objc implementa java.util.Map con una implementación de NSDictionary, sin necesidad de escribir y traducir una versión de Java ya que solo usa APIs de iOS.

Encuentro que la variante MVP en la que se basa Android es un paso en la dirección correcta para aislar la lógica empresarial de una aplicación. Sin embargo, si desea lograr una mejor separación de las preocupaciones, y como resultado una lógica de dominio / negocio más reutilizable, recomiendo usar el patrón Presenter First (que se menciona brevemente en el comentario). Aparte de la disminución de acoplamiento se presta bien a TDD y le permite a la unidad de prueba de toda su lógica de negocio.

Comencé recientemente un repo de GitHub con los primeros ejemplos de Presenter para Android. Debido a la complejidad de la arquitectura de Android, no es fácil implementar el patrón. Las vistas tienden a ser "más gordas" de lo que parece ser aceptable en una aplicación normal de Presenter First, principalmente debido al ciclo de vida de la actividad y otras rarezas. He hecho todo lo posible para desacoplar la lógica de negocios de la plataforma, pero definitivamente hay margen de mejora. Puede encontrar los ejemplos en:

http://github.com/olerass/presenter-first-android

Tal vez usted puede utilizar algunas ideas de allí? O incluso mejor contribuir con algunos de los suyos.

  • MVP para la actividad con múltiples fragmentos
  • ¿Cómo usar las Preferencias Compartidas en MVP sin Dagger y no hacer que Presenter dependa del contexto?
  • Explicación de Android MVP
  • Dagger 2 e implementaciones de interfaz
  • En el patrón MVP, ¿deben los adaptadores sujetar modelos o el presentador debe mantener los modelos y hacer que el adaptador lo haga referencia?
  • MVP de Android con Dagger 2 - Actividad con múltiples fragmentos
  • Estrategia de MVP de Android
  • Comprobación de Internet, dónde colocar al usar MVP, RX y Retrofit
  • MVP para Android: uso seguro Contexto en Presenter
  • Android Model-View-Presenter (MVP) Cómo devolver AsyncTask de ejecución larga
  • Ejemplo androide del presentador de la versión / ejemplos del regulador
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.