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

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Avanzado de Flutter

Curso Avanzado de Flutter

Anahí Salgado Díaz de la Vega

Anahí Salgado Díaz de la Vega

Enviando datos a Cloud Firestore

25/58
Recursos

Aquí encuentras el repositorio de esta clase.

Aportes 39

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Algunas partes del codigo se han quedado obsoletas por lo que hay que hacer unos cambios para que funciones bien.
Los cambios se hacen “cloud_firestores_api.dart”

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_avanzado/User/model/user.dart';

class CloudFirestoreAPI {

  final String USERS = "users";
  final String PLACE = "places";

  final FirebaseFirestore _db = FirebaseFirestore.instance;
  void updateUserDate(User user) async {
    DocumentReference ref = _db.collection(USERS).doc(user.uid);
    return ref.set({
      'uid': user.uid,
      'name': user.name,
      'email': user.email,
      'photoURL': user.photoURL,
      'myPlaces': user.myPlaces,
      'myFavoritePlaces': user.myFavoritePlaces,
      'lastSignIn': DateTime.now()
    },SetOptions(merge: true));
  }

}

Sobre 03:50 : El merge que va como segundo parametro en setData cuidado ya que se indica que no equivale a un commit y en firestore commit es otra cosa. El segundo parametro merge: true indica que en caso de ya existir el documento en la base de datos hace un update de los mismos (los mergea) y si no existe hace un set escribiendo un documento nuevo. En cambio si se pone merge como false en caso de que el documento exista lo sobreescribe eliminando el documento anterior. La diferencia con un merge true o un update es que si tenias un campo que no viene en el nuevo setData y estaba anteriormente en ese documento seria eliminado.
Por otro lado en cuanto a la referencia de commits existen tambien en firestore pero se suele usar para escritura en lotes.

Hola gente, tuve un problema al crear la función updateUserData en el archivo bloc_user.dart. El problema surgió debido a que había dos variable con el mismo nombre(User). Lo solucioné utilizando un as prefix.

import ‘package:trip_app/User/model/user.dart’ as userModel;

void updateUserData(userModel.User user) => _cloudFirestoreRepository.updateUserDataFirestore(user);

Espero les ayude de algo.

Este curso es bastante robusto, pero por sobre todo ¡Es genial!

Place place = Place(
      name: "Knuckles Mountains Range",
      description: "Hiking. Water fall hunting. Natural bath",
      urlImage: "https://images.unsplash.com/photo-1519681393784-d120267933ba?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80",
      likes: 3
  );
  Place place2 = Place(
      name: "Mountains",
      description: "Hiking. Water fall hunting. Natural bath’, 'Scenery & Photography",
      urlImage: "https://images.unsplash.com/photo-1524654458049-e36be0721fa2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80",
      likes: 10
  );```

Hola,

Comparto código que se ha actualizado con corte del 27 de septiembre de 2021. Específicamente en la acción del botón:

ButtonGreen(text: “Iniciar sesión con Gmail”,
onPressed: () {
userBloc.signOut();
userBloc.signIn().then((UserCredential user)
{
userBloc.updateUserData(Model.User(
uid: user.user.uid,
name: user.user.displayName,
email: user.user.email,
photoURL: user.user.photoURL));
});

            },

Espero les sirva en las futuras actualizaciones.

Saludos.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:generic_bloc_provider/generic_bloc_provider.dart';
import 'package:platzi_trips_app/User/repository/auth_repository.dart';
import 'package:platzi_trips_app/User/repository/cloud_firestore_repository.dart';
import 'package:platzi_trips_app/User/model/user.dart' as Model;

class UserBloc implements Bloc {

  final _auth_repository = AuthRepository();

  //Flujo de datos (Stream)
  //Stream de Firebase
 // Stream<FirebaseUser> streamFirebase = FirebaseAuth.instance.onAuthStateChanged;
  // ignore: deprecated_member_use
  Stream<User> streamFirebase = FirebaseAuth.instance.onAuthStateChanged;

  // ignore: deprecated_member_use
  Stream<User> get authStatus => streamFirebase;

  //Casos de uso
  //1. Hacer SignIn a la aplicacion Google
  // ignore: deprecated_member_use
  Future<User> signIn() {
    return _auth_repository.signInFirebase();
  }

  //2. Hacer signout
  signOut() {
    _auth_repository.signOut();
  }

  //3. Registrar usuario en base de datos
  final _cloudFirestoreRepository = CloudFirestoreRepository();
  void updateUserData(Model.User user) async => _cloudFirestoreRepository.updateUserDataFirestore(user);

  @override
  void dispose() {
    // TODO: implement dispose
  }
}```

Una semana en el mismo error y fue por intentar utilizar “RealTime DataBase” en lugar de “Cloud Firestore” 😦
jajaja

Desde la publicación de este curso hasta junio de 2021 Flutter ha tenido varios cambios, el NullSafety de dart y el cambio de FirebaseUser por User (o userCredential para el signIn) hace algo distinto el proceso, aquí tienen mi proyecto en github para que vean como se ve exactamente el mismo proyecto pero actualizado al año 2021. ```
https://github.com/Josehdez96/flutter-practice/tree/develop

Que tal amigos, alguien sabe por que apesar de no pasar userOwner, que es un parametro requerido, aun asi funciono la app?. Saludos, espero no sea muy tonta la pregunta

Agradezco mucho que vas mostrando los errores que cometes (como todos) y cómo los vas resolviendo, es de los mejores aspectos de este curso 😃

Para los que tuvieron problemas para conectarse con firebase database realtime, aqui les dejo mi proyecto en github el cual lo hice con mongodb localmente para que guarde los datos, la autitenticacion la sigo haciendo con google. Tambien podría implementar un backend con alguna plataforma y consumirla desde flutter.
proyecto con mongodb

Metí la pata creando una base de datos realtime y no me salían los registros, por lo tanto estuve buscando y en la nueva versión de Firebase se llama Cloud Firestore, debí haber intuido antes con el nombre pero al final lo logre.

Me marca esto: [Firestore]: Write failed at users/fAiJaADMXhWArCAl7kCtSKlWqKs1: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}

{
  "rules": {

     ".read": "auth.uid!=null",
      ".write": "auth.uid!=null"
  }

}```

ya he cambiado muchas veces el json de los permisos y de ninguna manera me ha dejado

mmm NO encontré los objetos para pegar 😦

en el minuto 5:46
Cual es la funcion del archivo cloud_firestore_repository ?

Mi cloud firestore se bugeo y no insertaba…no se si fue porque incluí la dependencia de firebase_core o porque estaba usando una version con un ‘+number’ al final. La UI de Firebase tampoco me dejaba nukear la DB! tuve que borrar todo desde Firebase CLI

https://firebase.google.com/docs/firestore/manage-data/delete-data

Hola amigos, Si les sale este error al momento de hacer login:
E/AndroidRuntime: FATAL EXCEPTION: grpc-default-executor-0
Dale una revisada a este link: https://stackoverflow.com/questions/62318039/firebase-no-static-field-is-restricted-appengine-of-type-z-in-class-lio-grpc-int

Básicamente es agregar las dependencias implementation 'io.grpc:grpc-android:1.28.1’
implementation 'io.grpc:grpc-okhttp:1.28.1’
en el archivo build.gradle de tu proyecto android.

Esto funciono para mi espero y les sea de ayuda.

Si les sale este error al momento de hacer login:
E/AndroidRuntime: FATAL EXCEPTION: grpc-default-executor-0
Dale una revisada a este link: https://stackoverflow.com/questions/62318039/firebase-no-static-field-is-restricted-appengine-of-type-z-in-class-lio-grpc-int

Básicamente es agregar las dependencias implementation 'io.grpc:grpc-android:1.28.1’
implementation 'io.grpc:grpc-okhttp:1.28.1’
en el archivo build.gradle de tu proyecto android.

Esto funciono para mi espero y les sea de ayuda.

Pienso que el nombre de repository podría ser “UserDataRepository” porque esta clase debería abstraer al resto del código de la tecnología, framework, db que se use. El resto del código siempre va a usar “UserDataRepository”, independientemente de que decidamos cambiar Firestore por AWS por ejemplo

Al dar click en el botón login, se cerraba la sección, la única forma de corregir el error fue añadir las siguientes líneas en app/build.gradle

// Import the BoM for the Firebase platform
implementation platform(‘com.google.firebase:firebase-bom:29.2.0’)

// Declare the dependencies for the desired Firebase products without specifying versions
// For example, declare the dependencies for Firebase Authentication and Cloud Firestore
implementation 'com.google.firebase:firebase-auth’
implementation ‘com.google.firebase:firebase-firestore’
}

Eres la mejor profesora Anahi

Luego de mucho tiempo de análisis , estos son los cambios que debemos hacer a nuestro código para que quede totalmente optimizado y funcional 2022:

//Dentro de Sign_in_screen 
import '../../model/user.dart' as appModel;
	//Importamos primero la librería user como appModel para evitar conflictos de nombre con el User de firebase

	//Dentro del metodo onPressed: () async 

		//No deberíamos subir también la propiedad myFavoritePlaces ya que firebaseAuth no nos trae este valor y al nosotros pasarlo sin valor estará sobrescribiendo (con null) a este campo cuando en un futuro cuando el usuario tenga este campo en la base de 	datos

userBloc.signOut();

final UserCredential valueResponsed = await userBloc.signIn();
                   //el ? me indica que el parametro puede ser null, y el  ?? lo que hace es evaluar si es null, y en caso de serlo utiliza el valor de al lado es decir ''
           	           userBloc.updateUserData(appModel.User(
                        uid: valueResponsed.user?.uid??'',
                        name: valueResponsed.user?.displayName??'',
                        email: valueResponsed.user?.email?? '',
                        imgUrl: valueResponsed.user?.photoURL?? '',
                       // myFavoritePlaces: valueResponsed.user?.myFavoritesPlaces// Como sigIn me trae es la informacion de auth y no la guardada en firestore, utilizamos el merge true y no actualizamos estos campos, es decir NO APARECE EN el objeto de AUTH que nos responde el stream que escucha a la sesion asi que no existe este valor
                      // myPlaces: valueResponsed.user?.myPlaces // Lo mismo de arriba 

                        )
                    );

);


//Ahora  procedemos a eliminar estos campos en el  CloudFirestoreApi que creamos para dejar de esperar el valor:

    return userRef.set({
      'uid':user.uid,
      'name':user.name,
      'email':user.email,
      'photoURL':user.photoURL,
      'lastSignIn':DateTime.now()
    },SetOptions(merge: true));

     //Por ultimo modificamos el objeto User para que nos permita crear una instancia sin pasar los2  parámetros de los places (es decir hacerlos opcionales):

class User {
  final String uid;
  final String name;
  final String email;
  final String photoURL;
  final List<Place>? myPlaces;
//decidi colocarle ? a la lista ya que al usuario ingresar por primera vez no va a tener esta info
  final List<Place>? myFavoritePlaces; 
//lo mismo de arriba

  User({
    required this.uid,
    required this.name,
    required this.email,
    required this.photoURL,
    this.myFavoritePlaces,
    this.myPlaces,
  });
}

Primero que todo aca les comparto mi repositorio del commit de esta clase Repositorio que creria yo ya todo esta funcionado.

a dia de hoy entre los problema que e tedio con el curso desactualizado con la implementacion de flutter de “null safety” otro problema es el error de_ “PlatformException (PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 12500: , null))”_ Este problema es porque en firebase hay que completar la " Pantalla de consentimiento Oauth "
Fui a esta página ( https://console.developers.google.com/apis/credentials ) No olvides seleccionar tu proyecto en la lista (arriba a la izquierda). Luego vaya a “Pantalla de consentimiento Oauth”

otro problema que me salio despues a ese es que el emulador que cree (porque borre el que usaba hasta este punto del curso) no tenia la Play Store

Vamos muy bien.!!

Ok, datos guardados! 😉

El curso anterior no me gusto, era muy teórico pero este curso va supero bien, esta lo máximo.

Muy Buena la clase 😉

Buenas, a mi me hace todo correctamente pero no me esta insertando los datos en firestore, alguien sabe que puedo hacer???
Revise el codigo por todos lados y lo veo similar al de la clase.
Aguardo comentarios.

Queda!

Todo bien hasta ahora, muy claro el video la verdad

Buenas amigos, a alguien le lanzó un error de permisos insuficientes?

[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(Error performing setData, PERMISSION_DENIED: Missing or insufficient permissions., null)```

aja y userOwner no es un campo requerido? como puede correr la app si aun no ha pasado ese parametro?

Guardado OK.

Muuy bien!!

Excelente curso!!! PEEEEERO!!!
Insisto en que lograr arquitectura perfecta no siempre es recomendable. En este caso de places repository, tanto como en user, no veo demasiada perfección en dividir el _api y el _repository de cloud_frestore. Podrían integrar el mismo dart file y seria mucho mas fácil de seguir

Hola a todos, veo que a un compañero le pasa lo mismo que a mi, en el siguiente enlace él explica mejor todo lo que sucede, alguien ha podido solucionarlo, yo estoy revisando por otras partes y creo que el problema es del generic_bloc_provider, al parecer ya esta muy desactualizado, creo que el mejor provider de momento es precisamente provider o getx
Estoy mirando si puedo migrar el código a provider o getx, a ver si con eso se soluciona.
Si alguien ha podido solucionar el problema, se les agradece
Por otra parte, es algo muy jarto que los problemas los deba solucionar cada quien sin apoyo por parte de platzi, las dudas es muy complicado manejarlas y no hay con quien tratar estos temas, y obviamente por este medio es muy demorado esperar que algún compañero llegue a esta precisa anotación que hago y que pueda dar respuesta a esto, estas respuestas las debería dar el tutor o platzi directamente debería brindar un medio para estas consultas individuales

En el userBloc no se debería importar el FirebaseUser ya que se liga a una implementación o estoy equivocado?