Arquitectura

1

Patrones de Diseño en Android: Soluciones y Aplicación Práctica

2

Fundamentos de Arquitectura de Software y su Impacto en Proyectos

3

Arquitecturas en Android: MVC y MVVM

4

Desarrollo de una Billetera Virtual con Git y Android Studio

5

Arquitectura MVP: Modelo, Vista y Presentador en Desarrollo de Software

6

Arquitectura MVP: Implementación en Proyectos Android

7

Implementación de Arquitectura MVP en Android

8

Implementación de Loaders en Arquitectura MVP con Android

9

Arquitectura MVVM en Android: Comunicación entre Capas

Patrones de diseño

10

Patrones de Diseño en Android: Creacionales, Estructurales y Comportamiento

Patrones de diseño creacionales

11

Implementación del Patrón Singleton en Kotlin para Android

12

Patrón Singleton en Kotlin para Gestión de Estados en Android

13

Patrón Builder en Android: Creación de Objetos Complejos

14

Implementación del Patrón Builder en Clases de Usuario

15

Funciones de Alcance en Kotlin: Uso de Apply

16

Patrón Factory: Creación y Uso en Desarrollo de Software

Patrones de diseño estructurales

17

Patrón de Diseño Adaptador para Transformar Datos en Clases Java

18

Aplicación del Patrón Proxy en Transferencias Seguras

19

Patrón de Diseño Fast Add en Aplicaciones Android

Patrones de comportamiento

20

Patrones de Diseño: Implementación del Patrón Observer en Proyectos

21

Patrón Observer en Android: Implementación y Uso Práctico

22

Patrón Comando: Implementación y Gestión de Comandos en Kotlin

23

Comandos para Guardar y Leer Archivos en Android

24

Ejecución de Comandos y Debugging en Android Studio

Bonus: Architecture Components

25

Componentes de Android Jetpack para Mejora de Aplicaciones

26

Implementación de LiveData en Android para Ciclo de Vida

27

Implementación de Room en Android para Gestión de Base de Datos

28

Creación de Entidades y DAO en Base de Datos con Room en Kotlin

29

Conexión y manejo de transferencias en Room Database

30

Implementación de ViewModel en Arquitectura MVVM en Android

Bonus: Custom View

31

Creación de Vistas Personalizadas en Android con Custom View

Conclusiones

32

Patrones de Diseño y Componentes de Texto en Android

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Patrón Observer en Android: Implementación y Uso Práctico

21/32
Recursos

¿Cómo implementar el patrón de diseño Observer para manejar eventos de saldo disponible en Kotlin?

El patrón de diseño Observer es uno de los patrones de comportamiento más utilizados en el desarrollo de software por su capacidad para manejar la comunicación entre objetos de manera eficiente. En el contexto de una aplicación Android, su uso se destaca en el manejo de cambios de estado y la actualización automática de la interfaz de usuario. A continuación, revisaremos cómo puedes implementar este patrón para gestionar el saldo disponible.

¿Qué pasos seguir para crear el observador del saldo en Kotlin?

  1. Creación de la clase del observador:

    Comienza creando una nueva clase que manejará los eventos del saldo disponible. Esta clase será la observada y tendrá que implementar la interfaz Observer. Al implementar esta interfaz, se nos obligará a definir varios métodos esenciales como addObserver, removeObserver, y notifyChange.

    class BalanceObserver : Observable() {
        // Implementación de métodos es requerida
    }
    
  2. Definición de los métodos de la interfaz:

    • addObserver: Debes crear un método que registre un observador a nuestra lista de observadores, la cual puedes almacenar en una variable inmutable val observerList = mutableListOf<Observer>().
    override fun addObserver(observer: Observer) {
        observerList.add(observer)
    }
    
    • removeObserver: Al igual que addObserver, necesitaremos un método que remueva un observador.
    override fun removeObserver(observer: Observer) {
        observerList.remove(observer)
    }
    
    • notifyChange: Por último, cuando se produzca un cambio, el método notifyChange informará a todos los observadores sobre el nuevo valor, que se distribuirá a través de este método por medio de un bucle for.
    override fun notifyChange(newValue: Double) {
        for (observer in observerList) {
            observer.update(newValue)
        }
    }
    
  3. Creación de una función para cambiar el saldo disponible:

    Necesitamos una función pública que permita cambiar el saldo y notificar a todos los observadores sobre este cambio.

    fun changeBalance(newAmount: Double) {
        currentBalance = newAmount
        notifyChange(newAmount)
    }
    

¿Cómo integrarlo en una vista de Android?

  1. Instanciar dentro del Fragmento o Actividad:

    En el ciclo de vida adecuado del fragmento o actividad, como onViewCreated, se debe crear una instancia del observador.

    private lateinit var balanceObserver: BalanceObserver
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        balanceObserver = BalanceObserver()
        balanceObserver.addObserver(YourObserverImplementation())
    }
    
  2. Actualizar la interfaz de usuario:

    En el método update que debemos implementar al crear el observador, podemos actualizar directamente la vista cada vez que se notifique un cambio en el saldo.

    override fun update(newBalance: Double) {
        amountTextView.text = "Saldo: $newBalance"
    }
    

¿Cuáles son las mejores prácticas al usar el patrón Observer en Android?

  • Suscripción y desuscripción adecuada: Es crucial suscribirse y desuscribirse de los eventos en los momentos adecuados del ciclo de vida de la actividad o fragmento. La desuscripción debe realizarse cuando la actividad/fragmento se destruye para evitar fugas de memoria o excepciones de referencia nula.

  • Uso de genéricos: Considera implementar los observadores como genéricos para reutilizarlos en diferentes contextos y con distintos tipos de datos.

  • Eficiencia en la notificación de cambios: Asegúrate de que la notificación de cambios sea eficiente y se realice solo cuando sea necesario, para no afectar el rendimiento de la aplicación.

Al implementar correctamente el patrón Observer, facilitas la gestión del flujo de datos y mejoras la reactibilidad de tu aplicación, ofreciendo a los usuarios una experiencia más fluida y eficiente.

Aportes 9

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Me propuse como reto hacer lo que dice el profesor: que las interfaces sean genéricas para que nosotros podamos usarla con cualquier tipo de dato. Simplemente fue cuestión de modificarlas de esta manera:

interface Observable2<T> {
    fun addObserver(observer: Observer2<T>)
    fun removeObserver(observer: Observer2<T>)
    fun notifyObservers(newValue: T?)
}
interface Observer2<T> {
    fun notifyChange(newValue: T?)
}

También me propuse añadir la funcionalidad de eliminar todos los observers automáticamente cuando el Fragment se destruye, tal y como lo hace LiveData. La clase quedó de esta manera:

class AvailableBalanceObservable<T>(lifecycleOwner: LifecycleOwner) : Observable2<T>
    init {
        lifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
            fun removeAllObservers() {
                amountObserverList.clear()
                lifecycleOwner.lifecycle.removeObserver(this)
            }
        })
    }
    // Resto del código
}

Un LifecycleOwner es una interfaz que implementan todas las clases que tienen un ciclo de vida, en este caso un Fragment, pero también puede ser una Activity. En mi implementación, al iniciar la clase, se añade un observador al ciclo de vida del Fragment. Cuando el Fragment ejecuta onDestroy(), se eliminan todos los observers de la lista y se elimina el propio observer del ciclo de vida.

Finalmente, para construir la clase, basta con llamarla así:

class HomeFragment : Fragment(), HomeContract.View {
    private lateinit var availableBalanceObservable: AvailableBalanceObservable<Double>
    // Resto del código...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // Resto del código...
        availableBalanceObservable = AvailableBalanceObservable(viewLifecycleOwner)
    }
}

Con estos dos cambios, la clase tiene más funcionalidades y está más cerca a la implementación de LiveData

Ciclo de Vida de Una Actividad

O pueden verlo mas detallado aquí 😉

Los eventos del observable deberían delegarse al Presenterya que a la vista (fragment o activity) no debe tener conocimiento de esta lógica. Cuando se observe un cambio, este se notifica a la vista a través del mismo Presenter.

El reto implementado en Dart:

abstract class Observer<T> {
  void notifyChange(T newValue) {}
}
abstract class Observable<T> {
  void addObserver(Observer<T> observer) {}
  void removeObserver(Observer<T> observer) {}
  void notifyObservers(T newValue) {}
}
class AvailableBalanceObservable implements Observable<double> {
  final List<Observer> _observerList = [];
  double _amount = 0.0;

  void changeAmount(double newValue) {
    _amount = newValue;
    notifyObservers(_amount);
  }

  @override
  void addObserver(Observer observer) {
    _observerList.add(observer);
  }

  @override
  void removeObserver(Observer observer) {
    _observerList.remove(observer);
  }

  @override
  void notifyObservers(double newValue) {
    for (var observer in _observerList) {
      observer.notifyChange(newValue);
    }
  }
}

Es muy importante tener en cuenta que estas dos interfaces tienen una continua comunicacion en andorid nuestras activities tienen un ciclo de vida volatil (el OS destruye actividades que estan en segundo plano para optimizar recursos)al momento de llamar al metodo onDestroy es una muy buena practica desuscribirme de todos los eventos de ese observable.

No que la Vista se comunicaba con el Presentador y este con el Observable ? En este ejemplo se saltaron el Presenter jajaja

En este curso el docente ha explicado conceptos que en cursos anteriores fueron asumidos como ya conocidos por los estudiantes, lo cual fue un error, debido a que el curso se hacia confuso. Era como leer un libro sin conocer el idioma en el que está escrito.
El curso me ha sido de gran ayuda.

“$ $newValue” el primer simbolo de dolar es string para mostrarlo el segundo para mostrar el valor de la variable

Buenas practicas