signinwithemailandpassword - package firebase_auth firebase_auth dart
Flutter-Cómo pasar datos de usuario a todas las vistas (3)
Me encontré con otro problema debido a este problema , puedes comprobarlo aquí. Por lo tanto, la solución que encontré es un poco desordenada, creé una página de dardos de instancias por separado y la importé a cada página.
GoogleSignInAccount Guser = googleSignIn.currentUser;
FirebaseUser Fuser;
Guardé el usuario allí al iniciar sesión y verifiqué en cada StateWidget si era nulo
Future<Null> _ensureLoggedIn() async {
if (Guser == null) Guser = await googleSignIn.signInSilently();
if (Fuser == null) {
await googleSignIn.signIn();
analytics.logLogin();
}
if (await auth.currentUser() == null) {
GoogleSignInAuthentication credentials =
await googleSignIn.currentUser.authentication;
await auth.signInWithGoogle(
idToken: credentials.idToken,
accessToken: credentials.accessToken,
);
}
Este es mi código anterior que limpié en mi aplicación actual pero ahora no tengo ese código a mano. Simplemente echa un vistazo a un usuario nulo y vuelve a iniciar sesión
También lo hice para la mayoría de las instancias de Firebase porque tengo más de 3 páginas en mi aplicación y Heredados Widgets era demasiado trabajo
Soy nuevo en el mundo móvil y en el desarrollo de aplicaciones móviles, y tengo dificultades para transmitir los datos de los usuarios a través de mi aplicación.
He intentado varias cosas, pero ninguna me parece genial y estoy seguro de que hay patrones de mejores prácticas que debería seguir.
Debido a que hace que los ejemplos sean más fáciles, estoy usando firebase para la autenticación. Actualmente tengo una ruta separada para iniciar sesión. Una vez que inicie sesión, quiero el modelo de Usuario en la mayoría de las vistas para verificar los permisos sobre qué mostrar, mostrar información del usuario en el cajón, etc.
Firebase tiene una await firebaseAuth.currentUser();
¿Es una buena práctica llamar a esto en cualquier lugar donde pueda necesitar el usuario? Y si es así, ¿dónde está el mejor lugar para realizar esta llamada?
El código de aleteo muestra un gran ejemplo de autenticación de usuarios antes de permitir escrituras. Sin embargo, si la página necesita verificar la autenticación para determinar qué compilar, la llamada asíncrona no puede ir en el método de build
.
estado inicial
Un método que he intentado es anular initState y comenzar la llamada para obtener el usuario. Cuando el futuro se complete, llamo a setState
y actualizo al usuario.
FirebaseUser user;
@override
void initState() {
super.initState();
_getUserDetail();
}
Future<Null> _getUserDetail() async {
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}
Esto funciona correctamente, pero parece una gran cantidad de ceremonias para cada widget que lo necesita. También hay un flash cuando la pantalla se carga sin el usuario y luego se actualiza con el usuario una vez que se complete el futuro.
Pasar al usuario a través del constructor.
Esto también funciona, pero es un montón de repetitivo para pasar al usuario a través de todas las rutas, vistas y sus estados que puedan necesitar acceder a ellos. Además, no podemos simplemente hacer popAndPushNamed
al transicionar rutas porque no podemos pasarle una variable. Tenemos que cambiar rutas similares a esta:
Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) => new MyPage(user),
));
Widgets Heredados
https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1
Este artículo mostró un buen patrón para usar InheritedWidget
. Cuando coloco el widget heredado en el nivel MaterialApp, los hijos no se actualizan cuando cambia el estado de autenticación (estoy seguro de que lo estoy haciendo mal)
FirebaseUser user;
Future<Null> didChangeDependency() async {
super.didChangeDependencies();
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}
@override
Widget build(BuildContext context) {
return new UserContext(
user,
child: new MaterialApp(
title: ''TC Stream'',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new LoginView(title: ''TC Stream Login'', analytics: analytics),
routes: routes,
),
);
}
FutureBuilder
FutureBuilder también parece ser una opción decente, pero parece ser mucho trabajo para cada ruta. En el siguiente ejemplo parcial, _authenticateUser()
obtiene el estado de usuario y configuración una vez finalizado.
@override
Widget build(BuildContext context) {
return new FutureBuilder<FirebaseUser>(
future: _authenticateUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return _buildProgressIndicator();
}
if (snapshot.connectionState == ConnectionState.done) {
return _buildPage();
}
},
);
}
Apreciaría cualquier consejo sobre patrones de mejores prácticas o enlaces a recursos para usar como ejemplos.
Para mi perezoso mathod, solo creo un nuevo archivo como userdata.dart y luego pongo cualquier variable en él, por ejemplo, como Dynamic Profile = null
dentro de userdata.dart
//only put this or anything u want.
dynamic Profile = null;
en startingpage.dart
//import that file
import ''../userdata.dart'';
class startingpage extends ...{
...
//set data to store..
Profile = ''user profile'';
...
}
para usar los datos solo declarar y usar en anotherpage.dart
//import that file
import ''../userdata.dart'';
class anotherpage extends...{
...
}
class .. State ...{
...
//set the data to variable
dynamic userdata = Profile;
print(''this is my lazy pass data'' + userdata.toString());
...
}
Recomiendo investigar más los widgets heredados; El siguiente código muestra cómo usarlos con datos de actualización asíncrona:
import ''dart:convert'';
import ''package:flutter/material.dart'';
import ''package:http/http.dart'' as http;
void main() {
runApp(new MaterialApp(
title: ''Inherited Widgets Demo'',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text(''Inherited Widget Example''),
),
body: new NamePage())));
}
// Inherited widget for managing a name
class NameInheritedWidget extends InheritedWidget {
const NameInheritedWidget({
Key key,
this.name,
Widget child}) : super(key: key, child: child);
final String name;
@override
bool updateShouldNotify(NameInheritedWidget old) {
print(''In updateShouldNotify'');
return name != old.name;
}
static NameInheritedWidget of(BuildContext context) {
// You could also just directly return the name here
// as there''s only one field
return context.inheritFromWidgetOfExactType(NameInheritedWidget);
}
}
// Stateful widget for managing name data
class NamePage extends StatefulWidget {
@override
_NamePageState createState() => new _NamePageState();
}
// State for managing fetching name data over HTTP
class _NamePageState extends State<NamePage> {
String name = ''Placeholder'';
// Fetch a name asynchonously over HTTP
_get() async {
var res = await http.get(''https://jsonplaceholder.typicode.com/users'');
var name = JSON.decode(res.body)[0][''name''];
setState(() => this.name = name);
}
@override
void initState() {
super.initState();
_get();
}
@override
Widget build(BuildContext context) {
return new NameInheritedWidget(
name: name,
child: const IntermediateWidget()
);
}
}
// Intermediate widget to show how inherited widgets
// can propagate changes down the widget tree
class IntermediateWidget extends StatelessWidget {
// Using a const constructor makes the widget cacheable
const IntermediateWidget();
@override
Widget build(BuildContext context) {
return new Center(
child: new Padding(
padding: new EdgeInsets.all(10.0),
child: const NameWidget()));
}
}
class NameWidget extends StatelessWidget {
const NameWidget();
@override
Widget build(BuildContext context) {
final inheritedWidget = NameInheritedWidget.of(context);
return new Text(
inheritedWidget.name,
style: Theme.of(context).textTheme.display1,
);
}
}