J'ai créé une page d'accueil et à partir de cet utilisateur, vous pouvez vous connecter à l'application et, dans l'écran suivant, l'utilisateur peut voir ses informations de profil (uniquement le nom du profil) et sous son bouton est signOut. L'utilisateur peut se déconnecter de l'application à l'aide du bouton SignOut, mais cela ne fonctionne pas pour moi.
Je veux appeler la méthode signOut à partir de main.Dart en appuyant sur le bouton signOut dans details.Dart (les deux classes sont dans un fichier différent)
Mais quand j'appuie sur le bouton SignOut dans les détails, rien ne se passe!
Et le code est donné ci-dessous:
main.Dart
import 'Dart:async';
import 'package:flutter/material.Dart';
import 'package:firebase_auth/firebase_auth.Dart';
import 'package:google_sign_in/google_sign_in.Dart';
import 'details.Dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
static bool _LoginButton = true;
void signOut(){
googleSignIn.signOut();
setState((){
_LoginButton = true;
});
print(_LoginButton);
print("User Signed Out");
}
Future<FirebaseUser> _signIn() async{
if(_LoginButton==true){
setState((){
_LoginButton=false;
});
GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
FirebaseUser firebaseUser = await firebaseAuth.signInWithGoogle(idToken: googleSignInAuthentication.idToken, accessToken: googleSignInAuthentication.accessToken);
print("Username is "+firebaseUser.displayName);
setState((){
_LoginButton = true;
});
Navigator.Push(context, MaterialPageRoute(builder: (context) => details(firebaseUser.displayName,signOut)));
return firebaseUser;
}
}
bool _LoginButtonBool(){
return _LoginButton;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Google auth with firebase"),),
body: Center(
child: _LoginButtonBool()?Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
MaterialButton(onPressed: _LoginButtonBool() ? () => _signIn().then((FirebaseUser firebaseuser ) =>print(firebaseuser)).catchError((e) => print(e)): null,
child: Text("Login"),color: Colors.orange,),
],
),
):CircularProgressIndicator(backgroundColor: Colors.greenAccent.withOpacity(0.01),),
),
);
}
}
détails.
import 'package:flutter/material.Dart';
import 'package:flutter_auth/main.Dart';
class details extends StatelessWidget {
String name;
final Function callback;
details(this.name,this.callback);
@override
Widget build(BuildContext context) {
return Scaffold(
body:Center(child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(name),
MaterialButton(onPressed: () => callback,
child: Text("Log out"),color: Colors.orange),
],
),),
);
}
}
Vous devez faire attention à ce que vous essayez de faire, car vous pouvez accéder à une page/un widget qui n'est pas monté. Imaginez que vous effectuez une pushReplacement(new MaterialPageroute(...))
. La page précédente n'est plus disponible dans l'arborescence, vous ne pouvez donc pas y accéder ni aucune de ses méthodes.
À moins que vous n'ayez une relation parent-enfant claire dans votre arborescence, vous devez retirer votre logique des classes de logique externe ou métier. Ainsi, vous êtes sûr d'appeler des instances actives de vos classes.
Voici un exemple de ce que vous pourriez utiliser pour contourner l'objet métier. Ce serait encore mieux si vous utilisez d'autres modèles comme BLOC, ScopedModel, Streams, etc. Mais pour des raisons de simplicité, je pense que cela devrait suffire.
import "package:flutter/material.Dart";
void main() {
runApp(MyApp(new Logic()));
}
class Logic {
void doSomething() {
print("doing something");
}
}
class MyApp extends StatelessWidget {
final Logic logic;
MyApp(this.logic);
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage(widget.logic),
);
}
}
class HomePage extends StatelessWidget {
final Logic logic;
HomePage(this.logic);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
onPressed: () { Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => AnotherPage(logic),
))},
child: Text("Go to AnotherPage"),
),
),
);
}
}
class AnotherPage extends StatelessWidget {
final Logic logic;
AnotherPage(this.logic);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
onPressed: logic.doSomething,
child: Text("Press me"),
),
),
);
}
}
Si vous souhaitez toujours appeler une fonction dans l'autre page et que vous êtes sûr que la page est montée (vous avez fait un Push
au lieu d'un pushReplacement
), vous pouvez procéder comme suit. (manipuler avec soin)
class HomePage extends StatelessWidget {
HomePage();
void onCalledFromOutside() {
print("Call from outside");
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
onPressed: () { Navigator.of(context).Push(
MaterialPageRoute(
builder: (context) => AnotherPage(onCalledFromOutside),
))},
child: Text("Go to AnotherPage"),
),
),
);
}
}
class AnotherPage extends StatelessWidget {
final Function callback
AnotherPage(this.callback);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
onPressed: callback,
child: Text("Press me"),
),
),
);
}
}
Importez la classe HomePage dans DetailsPage et créez-en une nouvelle instance, puis appelez la méthode souhaitée si elle est publique.