El Arsenal de Android – Arquitectura

Shuttle proporciona una forma moderna y segura de pasar grandes objetos serializables con objetos Intent o guardarlos en objetos Bundle para evitar bloqueos de aplicaciones.

Las empresas a menudo sufren los efectos secundarios negativos de los riesgos introducidos en la ingeniería de software del día a día. Estos efectos secundarios negativos incluyen tiempo y dinero invertidos en investigaciones de fallas de aplicaciones, correcciones de fallas de aplicaciones, pruebas de control de calidad, publicación de soluciones rápidas y control adicional mediante revisiones de código.

Shuttle reduce el alto nivel de gobernanza requerido para interceptar el código que induce la excepción de transacción demasiado grande:

  1. almacena el serializable y pasa un identificador para el serializable
  2. usando un pequeño paquete para transacciones de billetera
  3. evitar bloqueos de aplicaciones debido a excepciones de transacciones demasiado grandes
  4. habilitar la recuperación del Serializable almacenado en el destino.

¿Por qué seguir gastando más tiempo y dinero en gobernanza mediante revisiones de código? ¿Por qué no aceptar el problema proporcionándole una solución?

Al imaginar, diseñar y crear arquitectura, se tuvieron en cuenta los atributos de calidad y las mejores prácticas. Estos atributos incluyen, entre otros, la facilidad de uso, la legibilidad, el reconocimiento, la reutilización y el mantenimiento.

antecedentes

El marco Shuttle lleva el nombre del transporte de mercancías en la industria del transporte de mercancías. Las empresas de mudanzas y almacenamiento experimentan escenarios en los que los grandes camiones de mudanzas no pueden transportar mercancías hasta su destino (almacenes, hogares, etc.). Estos escenarios podrían ocurrir debido a restricciones en la carretera, camiones con sobrepeso de cargas grandes y más. Como resultado, las empresas utilizan pequeñas furgonetas Shuttle para transportar pequeños lotes de mercancías en varios viajes para entregar todo el envío.

Una vez completada la entrega, los empleados retiran los restos de carga de las camionetas y camiones lanzadera. Esta actividad de limpieza es uno de los últimos pasos del trabajo.

El marco de Shuttle tiene sus raíces en estos escenarios: crear un objeto de paquete de carga más pequeño que se utilizará para entregar con éxito datos al destino, transporta la carga grande correspondiente a un almacén y la almacena para su recogida conectando la carga más pequeña con la carga más grande. mediante un identificador que proporciona una única fuente de información (interfaz Shuttle) que se utilizará para el transporte de mercancías que proporciona funciones de conveniencia para retirar la carga (automáticamente o bajo demanda)

Próximamente

Otras pruebas.

Para comenzar

Consulte la documentación y la aplicación de demostración como punto de partida. La documentación se encuentra en el directorio “documentación” de cada módulo. Además, los documentos de modelado del proyecto se encuentran en el directorio de modelado del proyecto.

Para usar los artefactos de dependencia de Maven con Gradle, agregue lo siguiente a los archivos build.gradle correspondientes:

    implementation 'com.grarcht.shuttle:framework:1.0.0-alpha01' // Needed
    implementation 'com.grarcht.shuttle:framework-integrations-extensions-room:1.0.0-alpha01' // Needed
    implementation 'com.grarcht.shuttle:framework-integrations-persistence:1.0.0-alpha01'  // Needed depending on the set up
    implementation 'com.grarcht.shuttle:framework-addons-navigation-component:1.0.0-alpha01'  // Optional for integration with the Navigation Component

Uso sugerido

Para los usuarios finales que desean incluir Shuttle Framework en un proyecto, la mejor manera de comenzar es usar la interfaz Shuttle con el objeto CargoShuttle como implementación. Esta interfaz proporciona una única fuente de verdad.

Ejemplo de uso con Intents

Para transportar datos con objetos Shuttle e Intent, puede hacer lo siguiente:

    val cargoId = ImageMessageType.ImageData.value
    val startClass = MVCFirstControllerFragment::class.java
    val destinationClass = MVCSecondControllerActivity::class.java
    shuttle.intentCargoWith(context, destinationClass)
        .transport(cargoId, imageModel)
        .cleanShuttleOnReturnTo(startClass, destinationClass, cargoId)  // Important: this ensures cargo is not retained in the Warehouse when not needed
        .deliver(context)

En su destino, puede cargar datos con Shuttle haciendo lo siguiente:

    MainScope().async {
        getShuttleChannel()
            .consumeAsFlow()
            .collect { shuttleResult ->
                when (shuttleResult) {
                    ShuttlePickupCargoResult.Loading -> {
                        view?.let { initLoadingView(it) }
                    }
                    is ShuttlePickupCargoResult.Success<*> -> {
                        showSuccessView(view, shuttleResult.data as ImageModel)
                        cancel()
                    }
                    is ShuttlePickupCargoResult.Error<*> -> {
                        showErrorView(view)
                        cancel()
                    }
                }
            }
    }

Uso de muestra con el complemento de navegación y enlace de datos

La vista inicial:

    val cargoId = ImageMessageType.ImageData.value
    val startClass = MVVMNavFirstViewFragment::class.java
    val destinationClass = MVVMNavSecondViewActivity::class.java

    navController.navigateWithShuttle(shuttle, R.id.MVVMNavSecondViewActivity)
        ?.logTag(LOG_TAG)
        ?.transport(cargoId, imageModel as Serializable)
        ?.cleanShuttleOnReturnTo(startClass, destinationClass, cargoId)
        ?.deliver()

La vista de destino:

      onPropertyChangeCallback = object : OnPropertyChangedCallback() {
            override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
                when (propertyId) {
                    BR.shuttlePickupCargoResult -> {
                        when (viewModel.shuttlePickupCargoResult) {
                            ShuttlePickupCargoResult.Loading -> {
                                view?.let { initLoadingView(it) }
                            }
                            is ShuttlePickupCargoResult.Success<*> -> {
                                if (null != view && viewModel.imageModel != null) {
                                    showSuccessView(view, viewModel.imageModel as ImageModel)
                                }
                            }
                            is ShuttlePickupCargoResult.Error<*> -> {
                                view?.let { showErrorView(it) }
                            }
                            else -> {
                                // ignore
                            }
                        }
                    }
                }
            }
      }

El modelo de visualización de destino:

        viewModelScope.launch {
            shuttle.pickupCargo<Serializable>(cargoId = cargoId)
                .consumeAsFlow()
                .collect { shuttleResult ->
                    shuttlePickupCargoResult = shuttleResult

                    when (shuttleResult) {
                        ShuttlePickupCargoResult.Loading -> {
                            notifyPropertyChanged(BR.shuttlePickupCargoResult)
                        }
                        is ShuttlePickupCargoResult.Success<*> -> {
                            imageModel = shuttleResult.data as ImageModel
                            notifyPropertyChanged(BR.shuttlePickupCargoResult)
                            cancel()
                        }
                        is ShuttlePickupCargoResult.Error<*> -> {
                            notifyPropertyChanged(BR.shuttlePickupCargoResult)
                            cancel()
                        }
                        else -> {
                            // ignore
                        }
                    }
                }
        }

Estados de la carga del transbordador

Al almacenar la carga transportada con Shuttle, el objeto devuelto es un Channel de tipo ShuttleStoreCargoResult.

Al recuperar la carga transportada por Shuttle, el objeto devuelto es un canal de tipo ShuttlePickupCargoResult.

Al retirar la carga transportada con Shuttle, el objeto devuelto es un canal de tipo ShuttleRemoveCargoResult.

Estos tipos de devolución son clases selladas con varios estados. Shuttle utiliza este tipo para promover el uso del patrón Loading-Content-Error (LCE) y patrones similares.

Al proporcionar estos estados, el consumo de aplicaciones puede realizar acciones para la interfaz de usuario, análisis y otros casos de uso.

Limpieza después de su uso

Para eliminar los datos de carga persistentes después de que no sean necesarios, se encuentran disponibles funciones útiles.

Arquitectura

Esta arquitectura de proyecto proporciona tanto la solución como el marco de la solución Building Block (SBB).

Formularios

El Solution Building Block (SBB) compone agrupaciones lógicas en sus respectivos módulos. Estos módulos incluyen lo siguiente:

  1. Estructura: Este módulo contiene los componentes fundamentales de la solución esencial para comenzar.
  2. Integraciones de marco: Estos módulos contienen los puentes / interfaces necesarios para integrar diferentes tecnologías en el módulo marco.
  3. Extensiones de integración del marco: Estos módulos contienen el código necesario para completar las soluciones con el módulo Framework a través de los módulos Framework Integration.
  4. Complementos del marco: Estos módulos son soluciones útiles o bloques de creación de soluciones (SBB) integrados en Shuttle Framework.

Integraciones y extensiones del marco

El diseño de Shuttle Framework permite flexibilidad al no imponer tecnologías particulares en los proyectos de los consumidores. Un ejemplo de esto incluye el módulo de persistencia que proporciona las interfaces necesarias para integrar extensiones con Shuttle Framework. Una de esas extensiones es la extensión Room, que le permite usar Room para mantener la carga.

Complementos de marco

Shuttle Framework es un bloque de creación de soluciones (SBB). Los complementos están destinados a incluir soluciones / SBB construidas sobre la base de Shuttle Framework. Un ejemplo de un complemento es el módulo de navegación que permite el uso programático de Shuttle Framework con el navegador del componente Arquitectura de navegación de Google.

Tecnologías utilizadas por Shuttle Framework

El diseño de Shuttle Framework incluye la eliminación de tecnologías forzadas a los consumidores y el empaquetado de grandes dependencias transitivas. A menudo, el paquete de Framework incluye bibliotecas receptivas, a pesar de su gran tamaño. Shuttle Framework utiliza Kotlin Coroutines para proporcionar la comunicación asincrónica necesaria para lograr sus objetivos.

Derecho

Si hay otros datos, como los objetos parcelables incluidos en los datos de la intención, la aplicación aún puede fallar debido a las excepciones de Transacción demasiado grande.

En EA / SA e Ingeniería de software, los pros y los contras a menudo se sopesan sobre los temas. En Android, se pueden pasar diferentes tipos de datos con objetos Bundle. Se considera una buena práctica utilizar objetos Parcelable sobre objetos serializables para aprovechar tiempos de carga más rápidos. Desafortunadamente, los objetos parcelables están altamente optimizados para la comunicación entre procesos (IPC) y no son seguros para el almacenamiento en disco. Por lo tanto, Google recomienda utilizar la serialización estándar o alguna otra forma de serialización. Para garantizar el almacenamiento y la carga adecuados de objetos, este proyecto utiliza objetos serializables estándar para almacenar datos. La desventaja de este enfoque es que las velocidades de carga son más lentas que con los objetos Parcelable. Este inconveniente también puede conllevar algunos riesgos, ya que las implementaciones tienen que esperar un poco más para que se carguen los objetos. Para reducir este riesgo, se han proporcionado los estados de carga antes mencionados y permiten a los consumidores gestionar la interfaz de usuario con indicación del progreso de la carga de su elección.

Las aplicaciones de demostración

Las aplicaciones de demostración presentan el problema al mostrar que uno de los casos de uso más comunes es el transporte de datos de imágenes a objetos serializables. Incluyen el uso de Shuttle con arquitecturas de estilo MVVM y MVC.

Debe usar Glide, Picasso o alguna otra biblioteca equivalente para trabajar con imágenes. En gobernanza, se ha descubierto que los datos de imágenes contribuyen a la excepción Transaction Too Large. Este caso de uso es el motivo por el que se utiliza para demostrar la simplicidad y eficacia de Shuttle.

Con MVVM, las actividades y los fragmentos son parte del componente Ver. ViewModel es el vínculo entre View y Model. Mantiene el estado de la vista. Puede realizar acciones desde Ver eventos y realizar acciones en el Modelo. Puede responder a eventos del modelo y manipular la vista.

En la aplicación de demostración, el componente ViewModel utiliza el componente Arquitectura ViewModel de Google. El mecanismo de notificación asíncrono utilizado en MVVM se proporciona mediante los canales de Kotlin, muy similares a los Observables de la biblioteca de enlace de datos de Google. El enlace de datos también se ha incluido en algunas demostraciones para mostrar la integración básica.

Con MVC, las actividades y los fragmentos son parte del componente del controlador. Los controladores reciben entradas y las modifican para modelos o vistas.

Licencia

La licencia del MIT

GRARCHT ™ 2021

Por la presente, otorga permiso, sin cargo, a cualquier persona que obtenga una copia de este software y los archivos de documentación asociados (el “Software”), para tratar el Software sin limitación, incluidos, entre otros, los derechos de uso, copia, modificación, fusión , publicar, distribuir, licenciar y / o vender copias del Software y permitir que las personas a las que se proporciona el Software lo hagan, en las siguientes condiciones:

El aviso de copyright anterior y este aviso de permiso deben incluirse con todas las copias o partes sustanciales del Software.

EL SOFTWARE SE PROPORCIONA “TAL CUAL”, SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA, INCLUYENDO, PERO NO LIMITADO A, LAS GARANTÍAS DE COMERCIABILIDAD, APTITUD PARA UN PROPÓSITO PARTICULAR Y NO INFRACCIÓN. EN NINGÚN CASO LOS AUTORES O TITULARES DE LOS DERECHOS DE AUTOR SERÁN RESPONSABLES DE CUALQUIER RECLAMO, DAÑO U OTRA RESPONSABILIDAD, YA SEA CONTRACTUAL, ILEGAL O DE OTRA FORMA, QUE SURJA O EN RELACIÓN CON EL SOFTWARE O EL USO U OTRO TRATAMIENTO DEL SOFTWARE.

.

Compruebe también

en vivo desde Droidcon, incluida la mayor actualización de Gemini en Android Studio y más lanzamientos del SDK de Android.

Acabamos de lanzar nuestro episodio de otoño de #TheAndroidShow en YouTube etcétera desarrollador.android.comy esta vez …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *