Arquitectura de Aplicaciones

1

Pasos para aprender Flutter Avanzado

2

¿Qué es una Arquitectura de software?

3

Tipos de Arquitecturas para Flutter

4

Arquitectura BLoC en Flutter

5

BLoC + Clean Architecture en Flutter

6

Estructurando nuestro proyecto utilizando la Arquitectura BLoC

7

Haciendo BLoC Singleton en Flutter

8

Aplicando Providers al Proyecto

Firebase y Flutter

9

Integrando Firebase Authentication, Cloud Firestore y Firebase Storage al proyecto

10

Integrando Firebase a Flutter para Android

11

Integrando Firebase a Flutter para iOS

12

Creación de Pantalla de Login con Flutter

13

Creando botones reutilizables en Flutter

14

Autenticación de Firebase con Google

15

Implementando Firebase Authentication en BLoC Pattern

16

Streams en Flutter

17

Manejando una sesión con Firebase Authentication y Flutter

18

Implementando Google SignOut en BLoC

19

Implementando Google SignOut en View

20

Monitoreando y validando la conexión al Sign con Google

21

Mostrando los datos de usuario de Google en la interfaz en Flutter

Cloud Firestore de Firebase en Flutter

22

¿Qué es Cloud Firestore de Firebase?

23

Analizando un modelo de datos no relacional

24

Creando un Modelo de datos en Cloud Firestore

25

Enviando datos a Cloud Firestore

26

Creando un Widget gradiente personalizado

27

Manejo de Desbordamiendo de Texto de Widget Text

28

Botón de Back en un Appbar en Flutter

29

Navegación entre pantallas en Flutter

30

Widget Text Appbar personalizado en Flutter

31

Widget TextField personalizado en Flutter

32

Creando una Safe Area para una interfaz que tiene un AppBar

33

Widget TextField con iconos en Flutter

34

Retocando el CardView

35

Mostrando imágenes en un CardView

36

Creando un botón de Submit en Flutter

37

Envío de datos de un fórmulario en Flutter

38

Subiendo datos a Firestore de Firebase

39

Formularios en Flutter

Acceso al Hardware con Flutter

40

Acceso a la cámara en Flutter

41

Librerías de acceso a Hardware en Flutter

Firebase Storage en Flutter

42

Qué es y cómo funciona Firebase Storage en Flutter

43

Subiendo una imagen a Firebase Storage desde Flutter

Querys avanzados en Cloud Firestore de Firebase en Flutter

44

Manejo de imágenes en Cloud Firestore

45

Cloud Firestore insertando referencias y arrays en la base de datos

46

Descargar imágenes de Firebase Storage y mostrarlas en Flutter

47

Procesando datos con BLoC Pattern

48

Trayendo datos de Cloud Firestore

49

Persistiendo datos de un usuario logueado

50

Aplicando Filtros en Cloud Firestore

51

Construyendo los Places en la pantalla de Home

52

Mostrando los Places en la pantalla de Home

53

Actualizando datos en tiempo real

54

Manejando la lógica de likes, como botón toggle.

55

Insertando y obteniendo referencias en datos de Firestore.

56

Usando el caché para cargar imágenes más rápido

57

StreamController, sink, add y StreamBuilder

Conclusiones

58

Conclusiones

Curso Avanzado de Flutter

Curso Avanzado de Flutter

Camila Barajas Salej

Camila Barajas Salej

Insertando y obteniendo referencias en datos de Firestore.

55/58

Lectura

En la clase anterior te expliqué cómo estaremos manejando la lógica de los usuarios que dan like a un Place. Lo haremos insertándo su referencia en el Place correspondiente.

1. En el archivo cloud_firestore_api.dart ya teníamos listo el método likePlace

Lo ajustaremos un poco para manejar varias lógicas:

  • Necesitamos cambiar el parámetro de entrada String idPlace por un objeto Place place además como tambien necesitamos insertar la referencia del usuario que le dio like, agregaremos el parámetro String uid.

La firma del método debe verse de la siguiente forma:

Future likePlace(Place place, String uid) async {}
  • Ahora necesitamos manejar el incremento o decremento de likes dependiendo de la acción: Like (se agrega uno) Dislike (se resta uno). Hasta el momento en ambos casos estamos incrementando el valor, sustituyamos eso por lo siguiente:
_db.collection(PLACES).document(place.id)
    .updateData({
        'likes': place.liked?likes+1:likes-1,
});

Notarás que ahora estamos poniendo el id del objeto place.

Ahora validemos si se debe isertar el usuario que le dio like o en el otro caso eliminarlo si le dio dislike, el método completo deberá verse así:

Future likePlace(Place place, String uid) async {
    await _db.collection(PLACES).document(place.id).get()
        .then((DocumentSnapshot ds){
       int likes = ds.data["likes"];

       _db.collection(PLACES).document(place.id)
           .updateData({
         'likes': place.liked?likes+1:likes-1,
         'usersLiked':
         place.liked?
         FieldValue.arrayUnion([_db.document("${USERS}/${uid}")]):
         FieldValue.arrayRemove([_db.document("${USERS}/${uid}")])
       });


    });
}

Mira el archivo completo aquí

2. Ahora reflejemos el cambio de este método por toda la arquitectura BLoC del proyecto

Ajustaremos los siguientes archivos:

  • cloud_firestore_repository.dart
    Pongamos la llamada al método así:
Future likePlace(Place place, String uid) => _cloudFirestoreAPI.likePlace(place,uid);

Mira el archivo completo aquí

  • bloc_user.dart
    Pongamos la llamada al método así:
Future likePlace(Place place, String uid) => _cloudFirestoreRepository.likePlace(place,uid);

Mira el archivo completo aquí

3. Por último regresemos al archivo card_image_list.dart

En el método setLiked() dentro colocamos setState() el cuál maneja el estado de la UI, pongamos la llamada a hacer like y reflejar en la base de datos userBloc.likePlace(place, widget.user.uid);

void setLiked(Place place){
      setState(() {
        place.liked = !place.liked;
        userBloc.likePlace(place, widget.user.uid);
      });
}

Una vez que ya todo está insertado lo único que nos faltará será reflejar en la UI que el estilo del corazón cambie, para eso pensemos lo siguiente:

Como ahora la responsabilidad de renderear el CardImageFabIcon está en el archivo card_image_list.dart (justo fue lo que trabajamos en la clase anterior), por lo tanto la responsabilidad del método buildPlaces del archivo cloud_firestore_api.dart será unicamente de construir una lista de objetos Places a partir del snapshot entregado por el stream.

1. La firma del método buildPlaces ahora será así:

Se debe añadir el objeto User como parámetro el cuál representará los datos del usario que está logeado, para entonces comparar y validar con la colección de usuarios que dieron like al Place y si alguno coincide. marcarlo como liked.

List buildPlaces(List placesListSnapshot, User user) {}

Dentro quitaremos toda la lógica que correspondía a construir el Card en su lugar recorreremos la lista del snapshot y construiremos la lista de objetos Place. El método debe verse de la siguiente forma:

List buildPlaces(List placesListSnapshot, User user) {
    List places = List();

    placesListSnapshot.forEach((p)  {
      Place place = Place(id: p.documentID, name: p.data["name"], description: p.data["description"],
          urlImage: p.data["urlImage"],likes: p.data["likes"]
      );
      List usersLikedRefs =  p.data["usersLiked"];
      place.liked = false;
      usersLikedRefs?.forEach((drUL){
        if(user.uid == drUL.documentID){
          place.liked = true;
        }
      });
      places.add(place);
    });
    return places;
}

Observa que en esta línea: List usersLikedRefs = p.data["usersLiked"]; estamos obteniendo la lista de usuarios que dieron like como una lista de referencias, para después recorrerlos si es que existen, eso lo indicamos con el símbolo ?.
Al recorrerlos comparamos si el uid de usuario logeado es igual a alguno de los que están registrados en el place y si lo es marcamos el objeto Place que estamos construyendo como liked con el valor de true.

Mira el archivo completo aquí

Por último como est método buildPlaces es llamado en el Stream hacemos lo siguiente

2. Regresemos al archivo card_image_list.dart y en los estados adecuados del Stream pongamos el llamado al método y pasemos como parámetro el objeto user.

  • Lo hacemos de esta forma en el estado active y done:
case ConnectionState.active:
  print("PLACESLIST: ACTIVE");
  return listViewPlaces(userBloc.buildPlaces(snapshot.data.documents, widget.user));
case ConnectionState.done:
  print("PLACESLIST: DONE");
  return listViewPlaces(userBloc.buildPlaces(snapshot.data.documents, widget.user));

Mira el archivo completo aquí

Mira el código completo aquí

Ahora vamos a la siguiente clase para hacer que la carga de imágenes sea mucho más ágil.

Aportes 18

Preguntas 0

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

con esta clase otro punto menos. cursoAvanzadoFlutter = cursoAvanzadoFlutter -1;

Bueno yo no e tenido problema con respecto a estas clases me funciona perfectamente la aplicación, como menciona el compañero Jaime Ortiz, quien lo ha estado desarrollando y poniendo atención a cada detalle y como funciona cada instrucción no tiene mayor problema. Solo tuve un pequeño error que estaba el cloud_firestore_api.dart que era en el List place = List(); tuve que cambiarlo a List<Place> places = List<Place>(); de ahi todo funciona correctamente.

Mucho desorden, me decepciono al final este curso, íbamos bien hasta la clase 38

Sorry pero hay bastantes cosas que no se solucionaron en estas dos clases. Deben revisarlo, hay fuga de informacion.

Decepcionante este curso…

malograron el funcionamiento de la aplicación, malaso de su parte, no habia necesidad de enredarse con esto

Deberían planificar mejor sus proyectos para definir todo lo que va a llegar, así no tendremos que estar haciendo cambio con errores super raros

se supone que era un curso de Flutter !!!

El problema es que el código publicado en Git, no va de acuerdo al avance de las clases, sino es el código final.

Muy buena la clase, para el que no entendió fue porque no están haciendo el proyecto a la par con Anahí.

Me gustó mucho el curso desde la perspectiva de las herramientas que se usaron y a que puntualmente también uso firebase, pero cometieron un grave error, y fue apuntar a una aplicación que usa base de datos y previamente necesita una planificación de esta. Se confunde mucho la temática respecto a flutter cuando se incurre en constantes refactorizaciones para ir haciendo que la app cumpla con cada nuevo requerimiento para el comportamiento con firebase y firestore.
Me hubiese gustado más trabajar con una aplicación menos funcional pero que tuviera un fuerte enfoque al lenguaje y framework, porque de momento me cuesta entender lo que hay detrás de los streams, bloc, singletones y el manejo de los screens.

https://github.com/GregVaz/flutter-course/tree/flutter-firebase
Igual si acaso alguien sigue el curso y tiene duda, acá dejo mi repo

https://github.com/adolfojara10/CursoFlutterAvanzado
Les dejo el link de mi repositorio por si acaso tienen alguna duda

Por si alguien sigue haciendo el curso.
Es interesante como se puede llevar a cabo las explicaciones aplicándolas a una implementación mucho muy actualizada.

//Metodo para mostrar todos los Places en la pantalla de home
//Asi como definir que Places ya se le ha dado like por parte
//del usuario loguado
List<Place> buildPlaces(
List<DocumentSnapshot> placesListSnapshot, modelUser.User user) {
List<Place> places = [];

placesListSnapshot.forEach((DocumentSnapshot place) {
  bool isLiked = false;
  //Obtenemos referencia del usuario
  //DocumentReference refUser = _dataBase.doc("$USERS/${user.userId}");

  Map<String, dynamic> data = place.data()! as Map<String, dynamic>;

  //Guardamos la lista de usuarios que les gusta el lugar
  List<dynamic>? usersLiked = data['usersLiked'];

  if (usersLiked != null) {
    usersLiked.forEach((userLiked) {
      //Guardamos cada elemento y lo seteamos como de tipo DocumentReference
      DocumentReference userReference = userLiked;

      //Comparamos id del usuario que le dio like con el id del usuario que se encuentra logueado
      //Si es igual seteamos la variable isLiked = true para controlar el boton de corazon se rellene para este usuario
      if (userReference.id == user.userId) {
        isLiked = true;
      } else {
        isLiked = false;
      }
    });
  } else {
    isLiked = false;
    print("No hay likes de ningun usuario");
  }

  places.add(Place(
      id: place.id,
      likes: data['likes'],
      name: data['name'],
      description: data['description'],
      urlImage: data['urlImage'],
      liked: isLiked));
});
return places;

}

No explican detalladamente lo que esta en el código y hace que tengamos muchos errores.

En doc-doc buscamos talento con capacidades proactivas, ganas de desarrollar nuevas habilidades, que nos ayuden a llevar el equipo a otro nivel, inspirados por los poderes que la tecnología trae a un mundo que evoluciona.

Las principales tecnologías con las que tendrás contacto son:
• Flutter (Dart) • Node (TypeScript) • GCloud • MySQL
• GraphQL • Python

Si te interesa crear un gran impacto en la salud de las personas y tener un lugar donde poder hablar de ciencia, filosofía, además de tecnología, en doc-doc te vas a sentir como en casa.

Nos gusta conocer a las personas.

Escríbeme a [email protected]

Genial!! 😃 Me encantó!

Muy buena clase…
Me temo que para los que se quejan de la sobre-escritura de código, quizás sea por que no acostumbran fraccionar las clases en ramas de git.
Creo que una de las características interesantes a agregar sería el mantener un IconData sostenido según el status de liked, de esta forma el usuario recordará a ¿qué imágenes le dió like? y a ¿cuáles no?
Gran clase