MVI con máquina de estado. Módulos | de Nikolái Kotchetkov | Medio

Parte III. Lógica multimódulo y multiplataformaAprendizaje directo de la introducción de la arquitectura State Machine MVI por Ulyana Kotchetkova Esta es la tercera parte de la serie MVI con State Machine que describe cómo modular su lógica y escribir una lógica de promoción multiplataforma. Consulte las otras partes de la serie para obtener una descripción general de los pasos básicos y las herramientas útiles para mezclar: El código fuente del artículo y la biblioteca central muy básica están disponibles en GitHub. La biblioteca es completamente opcional, en caso de que quiera ahorrar algo de tiempo si no escribe su propio núcleo. Los fragmentos de código de este artículo se basan en el módulo de inicio de sesión y el módulo multiplataforma de registro del ejemplo ampliado: «Aplicación de bienvenida». Luego, los módulos se implementan en la aplicación principal.

Contenidos

Nota sobre multiplataforma

Aunque la lógica para el flujo de registro es coherente, no pude implementar la vista de registro en AndroidMain Source of Registration Module debido a algunos errores de configuración o fallas en la multiplataforma de Kotlin. El problema es que las fuentes de Android no pueden importar dependencias compartidas de otros módulos compartidos. Si alguien pudiera ayudarme a solucionar este problema se lo agradecería mucho 🙂

Aplicaciones multimódulo

Tomemos un ejemplo más complicado con un flujo de múltiples pantallas como la incorporación de un cliente imaginario:Flujo de la pantalla de aplicación de BienvenidaEl usuario debe aceptar los términos y condiciones e ingresar su dirección de correo electrónico. Luego, la lógica verifica si ya está registrado o si es un cliente nuevo y ejecuta el flujo apropiado para iniciar sesión o registrar un usuario en el diagrama de estado de la aplicación:Diagrama de estado de la aplicación de bienvenida El proyecto consta de los siguientes módulos:

  • Bienvenida – proceso común: precarga, entrada de correo electrónico, verificación del cliente, listo.
  • commoncore – abstracciones comunes para crear aplicaciones: despachadores, recursos, etc.
  • commonapi: módulo multiplataforma común para conectar la aplicación principal con los módulos.
  • inicio de sesión: flujo de inicio de sesión.
  • commonregister — Lógica de registro para múltiples plataformas.
  • registro: módulo de visualización de Android para el registro (desconectado porque no lo implementé en la fuente de Android de Commonregister. Consulte la nota anterior)

API común

Como puede ver en el diagrama anterior, la lógica de inicio de sesión y registro general comienza después de que se verifica el correo electrónico y se recibe la respuesta sobre el estado de registro del usuario. Cada flujo de módulo de funciones comienza con una pantalla de ingreso de contraseña, aunque es diferente para todos. Cada flujo de módulo vuelve al flujo principal:

  • cuando el flujo se completa con éxito, cambia a «Completado».
  • cuando el usuario vuelve a hacer clic, vuelve a la entrada de correo electrónico

Luego, definamos la API de interacción de flujo principal: interfaz del módulo host Colocamos la definición en el módulo disponible para todos los módulos: commonapi, y exponemos la interfaz sobre el contexto de estado común de la siguiente manera: característica- Contexto del módulo También necesitamos una forma de iniciar el flujo de características Una vez que sepamos que cada función se inicia con la dirección de correo electrónico de un usuario, tengamos una interfaz común que cree un estado de inicio para cada máquina de estado del módulo de funciones: Arrancador de flujo de funciones

flujo de módulo

Cada módulo tiene su propio sistema sellado de gestos/estados de vista: Gestos del módulo y estados de la interfaz de usuario Cada módulo es completamente independiente en términos de gestos y estados de la interfaz de usuario, y también tenemos un conjunto patentado de «abstracciones prácticas» para cada módulo: renderizadores, fábricas , casos de uso, etc. Consulte el código fuente para obtener más detalles. Ahora que hemos diseñado y probado todos los flujos de módulos, necesitamos encontrar una forma de conectar sistemas completamente heterogéneos con un solo flujo de estado.

Adopción de flujos de características

Dado que el sistema de visualización y gestos está vinculado a la máquina de estado mediante genéricos, necesitamos crear algunos adaptadores para ejecutar el flujo dentro del flujo de estado de la aplicación principal. Cosas para hacer:

  • Personalice los gestos para integrarlos con el flujo de gestos de saludo.
  • Personalice los estados de vista para que el sistema de visualización pueda mostrarlos.
  • Ejecute el flujo de estado extranjero de alguna manera dentro de la máquina de estado de bienvenida.

gestos y ver estados

Para heredar los gestos del módulo de funciones, existen al menos dos soluciones:

  1. Libérese de los sistemas sellados y herede la interfaz común de marcadores base de API para todos los gestos y estados de vista. Si bien la solución es simple, no es ideal porque perdemos la seguridad de tipo en controles extensos al enviar gestos en nuestros estados. Así que dejémoslo…
  2. Cree un adaptador de envoltorio que envuelva el estado de vista/gesto externo y desenvuélvalo más tarde cuando lo pase a la implementación concreta. Esto significa que el soporte del compilador y la seguridad de tipos no se pierden. Sigamos esta ruta.

Adaptador de gestos: herencia de estados de interfaz de usuario externos Adaptador: herencia de estados de interfaz de usuario externos

Mostrar implementación

Ahora vamos a crear componibles de características y hosts para aprovechar nuestros adaptadores.

  1. Delegamos la representación de los estados de la interfaz de usuario para que presenten componentes componibles al desempaquetar los estados propietarios del sistema de estado de vista común.
  2. Envolvemos cada gesto característico en el sistema maestro de gestos y lo pasamos a nuestro modelo para su procesamiento.

Adquisición de un sistema de estado de máquinas extranjeras

Lo último que debemos hacer para poder ejecutar un módulo de funciones en nuestro sistema host es ejecutar los estados de la máquina de funciones en nuestra máquina de estado de la aplicación. Recuerde que vinculamos tanto el sistema de gestos como el sistema de estado de ui a nuestras interfaces de máquina de estado y estado de máquina: interfaces de máquina de estado básicas Dado que nuestros estados tienen una interfaz de estado simple y clara y tienen un ciclo de vida simple, podríamos encapsular la función ¡La lógica de la máquina de estado en nuestro estado de host con ProxyMachineState ejecutando una máquina de estado secundaria dentro del estado de host! Cada vez que se inicia un ProxyMachineState, inicia su instancia interna de una máquina de estado que está vinculada a los sistemas de visualización y gestos de funciones. También une dos sistemas de vista/gesto incompatibles al envolver/desenvolver un sistema y adaptarlo a otro llamando a dos métodos de adaptador:

  • mapGesture: asigna el gesto del sistema principal al sistema secundario si tiene una asignación relevante (podríamos devolver nulo para omitir el procesamiento de gestos).
  • mapUiState: asigna el estado secundario de la interfaz de usuario al sistema de estado principal de la interfaz de usuario. Por ejemplo, envolviendo un estado secundario en un contenedor, como hicimos en la sección anterior.

Juntemos todo y creemos un proxy de flujo de inicio de sesión para aclarar las cosas: Proxy de flujo de inicio de sesión Analicemos los métodos implementados:

  • init(): crea un estado inicial para una máquina de estado proxy. Obtenemos una interfaz FlowStarter del componente DI de la función para crear un estado de inicio e inicializar la máquina de estado del proxy. El elemento secundario requiere que WelcomeFeatureHost proporcione backToEmailEntry y métodos de interacción de host completos, así que implementémoslo aquí y proporcionemos la instancia de estado de fábrica del componente. El proxy implementa WelcomeFeatureHost cambiando la máquina host a correo o estado completo.
  • mapGesture: asigna un gesto del sistema de gestos principal al sistema secundario. Puede desenvolver el gesto que implementamos en la sección anterior, como el gesto de retroceso, heredar un sistema en otro o descartar gestos irrelevantes devolviendo nulo desde su implementación.
  • mapUiState: realiza una transición de un sistema de estado de interfaz de usuario subordinado al sistema principal. Simplemente envolvemos uno del otro como diseñamos de antemano.

cambiar las corrientes

Después de implementar los estados de proxy para los flujos de inicio de sesión y registro, usamos nuestra fábrica de estados para crearlos y cambiar la máquina de estado del host al flujo apropiado según el resultado de la verificación del correo electrónico: Verificación de correo y cambio de secuencia

Conclusión

Espero que alguien encuentre útil el artículo (y la biblioteca si quiere tomarlo por lo que es) para crear aplicaciones complejas de pantalla múltiple con capacidad de módulo múltiple. Este enfoque tiene como objetivo darle la mayor libertad posible para implementar su lógica. Por supuesto, no es una bala de plata, pero la flexibilidad de estructurar su aplicación en este patrón funciona bien en la mayoría de los escenarios. Puede combinar todos los pasos de su aplicación en un solo flujo de estado de máquina, o crear modelos de vista separados e insertarlos en las partes de su diagrama de biblioteca de navegación. Y también puede usar cualquier arquitectura dentro de sus estados: corrutinas simples para obtener los datos, flujos RxJava complejos o incluso otra biblioteca MVI en casos más complejos. La biblioteca se creó teniendo en cuenta el enfoque multiplataforma, ya que no contiene ninguna dependencia de plataforma concreta y las extensiones de rutinas son opcionales. Esto le permite construir su lógica de vista una vez y adaptar su salida a los componentes de vista de su plataforma. La biblioteca completa y el código de muestra están disponibles en GitHub. ¡Que te diviertas!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.