1
votes

Comment passer l'utilisateur à une route nommée avec un widget avec état à l'aide de Navigator in Flutter?

Ma configuration
  • Route de connexion - vérifie de manière asynchrone si un utilisateur est connecté
  • Route d'enregistrement - Se compose d'un widget avec état principal et de plusieurs widgets enfants sans état qui dépendent des informations de l'utilisateur connecté

Mon idée

  • Une fois la connexion de l'utilisateur identifiée sur la route de connexion, utilisez Navigator pour transmettre l'objet utilisateur à la route d'enregistrement
  • les widgets enfants peuvent recevoir l'objet utilisateur via leur constructeur

Mon problème

  • l'objet utilisateur n'est pas "arrivé" dans le widget avec état de la route d'enregistrement

Files

Voici les extraits de code pertinents à vérifier (je les ai ajoutés à partir de fichiers plus complexes et j'espère que toutes les importations sont correctes):

Main.dart

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class CheckinList extends StatelessWidget{
    FirebaseUser user = null;

    CheckinList({this.user = null});

    @override
    Widget build(BuildContext context) {
        return Container(
            padding: EdgeInsets.all(30.0),
            child: Text(user['name'])
        );
    }
}

LoginView.dart

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'checkinList.dart';

class CheckinView extends StatefulWidget {
    final FirebaseUser user;

    CheckinView({this.user});

    @override
    CheckinViewState createState() {
        print("[CheckinView - user] $user");
        return CheckinViewState();
    }
}

class CheckinViewState extends State<CheckinView> {
    FirebaseUser _currentUser;

    @override
    void initState() {
        super.initState();

        setState((){
            _currentUser = widget.user;
        });
    }

    @override
    Widget build(BuildContext context) {

        print("[CheckinViewState - widget.user] " + widget.user.toString());

        return Scaffold(
            body: new Column(
                children: <Widget>[
                    CheckinList(user: _currentUser)
                ]
            )
        );
    }
}

CheckinView.dart

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class LoginView extends StatefulWidget {
    @override
    LoginViewState createState() => LoginViewState();
}

class LoginViewState extends State<LoginView> {
    @override
    void initState() {
        super.initState();

        checkLoginAndRedirect();
    }

    void checkLoginAndRedirect() async {
        FirebaseAuth.instance.currentUser().then((FirebaseUser currUser){
            if(currUser != null){
                print("[LoginView - user] $currUser");
                Navigator.pushNamed(context, '/checkin', arguments: {currUser});
            }
        });
    }
}

CheckinList.dart

import 'package:flutter/material.dart';
import 'loginView.dart';
import 'checkinView.dart';

void main() {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(MyApp());
}

class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            initialRoute: '/',
            routes: <String, WidgetBuilder>{
                '/': (BuildContext context) => LoginView(),
                '/checkin': (BuildContext context) => CheckinView(),
            }
        );
    }
}

1 commentaires

Je pense que c'est un double de stackoverflow.com/questions/56262655/... . J'ai eu le même problème. Cette réponse a fonctionné.


3 Réponses :


0
votes

Vous devez accéder aux données transmises en utilisant ModalRoute dans la méthode build , le code ci-dessous vous donnera une idée de la façon de le faire,

class LevelViewChildScreen extends StatelessWidget {
  UserModel user;

  @override
  Widget build(BuildContext context) {
    user = ModalRoute.of(context).settings.arguments;

    return LevelViewChild(user);
  }
}

class LevelViewChild extends StatefulWidget {
  UserModel user;

  LevelViewChild(this.user);


2 commentaires

Salut Ravinder, je vois d'où tu viens (le livre de cuisine) en fait, c'est encore beaucoup plus simple .. J'ajouterai la réponse ci-dessous ...


Oui, je sais déjà que vous pouvez passer une carte ou une liste, même si j'essayais juste d'aider.



1
votes

Solution
  • Les arguments doivent être extraits dans la méthode de construction du WidgetState (car c'est seulement là que nous avons le BuildContext)
  • Navigator gère automatiquement les arguments correctement, même avec des widgets avec état - MERCI FLUTTER TEAM !!!!

Mes fichiers adaptés

Main.dart

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class CheckinList extends StatelessWidget{
    FirebaseUser user = null;

    //// assign the user in your constructor
    CheckinList(FirebaseUser user){
        this.user = user;
    };

    @override
    Widget build(BuildContext context) {
        return Container(
            padding: EdgeInsets.all(30.0),
            child: Text(user['name'])
        );
    }
}

LoginView.dart em>

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'checkinList.dart';

class CheckinView extends StatefulWidget {
    //// leave the stateful class as usual

    @override
    CheckinViewState createState() => CheckinViewState();
}

class CheckinViewState extends State<CheckinView> {
    //// don't bother in the initState method as the BuildContext is missing here

    @override
    Widget build(BuildContext context) {

        //// access the passed arguments
        Map<String, dynamic> args = ModalRoute.of(context).settings.arguments;

        print("[CheckinViewState - widget.user] " + widget.user.toString());

        return Scaffold(
            body: new Column(
                children: <Widget>[
                    //// access the passed variables through 'args'
                    CheckinList(user: args.user)
                ]
            )
        );
    }
}

CheckinView.dart

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class LoginView extends StatefulWidget {
    @override
    LoginViewState createState() => LoginViewState();
}

class LoginViewState extends State<LoginView> {
    @override
    void initState() {
        super.initState();

        checkLoginAndRedirect();
    }

    void checkLoginAndRedirect() async {
        FirebaseAuth.instance.currentUser().then((FirebaseUser currUser){
            if(currUser != null){
                print("[LoginView - user] $currUser");
                //// pass a map as 'arguments' to be ready to pass along more variables in the future
                Navigator.pushNamed(context, '/checkin', arguments: {'user': currUser});
            }
        });
    }
}

CheckinList.dart em>

import 'package:flutter/material.dart';
import 'loginView.dart';
import 'checkinView.dart';

void main() {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(MyApp());
}

class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            initialRoute: '/',
            routes: <String, WidgetBuilder>{
                '/': (BuildContext context) => LoginView(),
                '/checkin': (BuildContext context) => CheckinView(),
            }
        );
    }
}

En savoir plus dans le livre de recettes à ce sujet:


0 commentaires

1
votes

Vous pouvez l'essayer. J'espère que cela pourra vous aider

class CheckinView extends StatefulWidget {
    RouteSettings settings = ModalRoute.of(context).settings /// <--- fixed here
    FirebaseUser user = settings.arguments; /// <--- fixed here

    @override
    CheckinViewState createState() {
        print("[CheckinView - user] $user");
        return CheckinViewState();
    }
}
class LoginViewState extends State<LoginView> {
    @override
    void initState() {
        super.initState();

        checkLoginAndRedirect();
    }

    void checkLoginAndRedirect() async {
        FirebaseAuth.instance.currentUser().then((FirebaseUser currUser){
            if(currUser != null){
                print("[LoginView - user] $currUser");
                Navigator.pushNamed(context, '/checkin', arguments: currUser); /// <--- fixed here
            }
        });
    }
}


0 commentaires