【问题标题】:How to pass user to named route with a stateful widget using Navigator in flutter?如何在颤动中使用 Navigator 将用户传递给具有状态小部件的命名路由?
【发布时间】:2020-04-18 15:07:52
【问题描述】:

我的设置

  • 登录路径 - 异步检查用户是否登录
  • 签入路线 - 由一个主要的有状态小部件和几个依赖于登录用户信息的无状态子小部件组成

我的想法

  • 在登录路由上识别出用户登录后,使用 Navigator 将用户对象传递给签入路由
  • 子小部件可以通过其构造函数接收用户对象

我的问题

  • 用户对象未在签入路线的有状态小部件中“到达”

文件

这里是要检查的相关代码 sn-ps(我是从更复杂的文件中添加的,希望所有导入都正确):

Main.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(),
            }
        );
    }
}

LoginView.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});
            }
        });
    }
}

CheckinView.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)
                ]
            )
        );
    }
}

CheckinList.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'])
        );
    }
}

【问题讨论】:

标签: flutter dart


【解决方案1】:

你可以试试。希望对你有帮助

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
            }
        });
    }
}
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();
    }
}

【讨论】:

    【解决方案2】:

    解决方案

    • 需要在 WidgetState 的 build 方法中提取参数(因为我们只有 BuildContext)
    • Navigator 会自动正确处理参数,即使使用有状态小部件 - 感谢 FLUTTER 团队!!!!

    我的改编文件

    Main.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(),
                }
            );
        }
    }
    

    LoginView.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});
                }
            });
        }
    }
    

    CheckinView.dart

    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)
                    ]
                )
            );
        }
    }
    

    CheckinList.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'])
            );
        }
    }
    

    在食谱中了解更多信息:

    【讨论】:

      【解决方案3】:

      您需要在build 方法中使用ModalRoute 访问传递的数据,下面的代码将告诉您如何操作,

      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);
      

      【讨论】:

      • 嗨,Ravinder,我知道你是从哪里来的(食谱),它更简单..我将在下面添加答案...
      • 是的,我已经知道你可以传递地图或列表,虽然我只是想帮忙。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 2017-05-03
      • 2021-01-03
      • 2019-12-29
      • 1970-01-01
      • 2020-07-24
      • 2020-08-06
      相关资源
      最近更新 更多