如何在Flutter中使用导航器通过状态控件将用户传递到命名路线?

时间:2019-12-29 16:27:10

标签: flutter dart

我的设置

  • 登录路线-异步检查用户是否已登录
  • 签入路线-包含一个主要的有状态小部件和几个无状态的子级小部件,这些小部件取决于已登录用户的信息

我的想法

  • 在登录路径上识别出用户登录后,使用导航器将用户对象传递到签入路径
  • 儿童小部件可以通过其构造函数接收用户对象

我的问题

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

文件

以下是要检查的相关代码段(我从更复杂的文件中添加了这些代码段,并希望我输入的所有内容正确无误):

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

3 个答案:

答案 0 :(得分:0)

您需要在ModalRoute方法内使用build访问传递的数据,下面的代码将让您知道如何做,

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

答案 1 :(得分:0)

解决方案

  • 需要在WidgetState的build方法中提取参数(因为只有那里有BuildContext)
  • 即使使用有状态的小部件,导航器也会自动正确地处理参数-谢谢FLUTTER TEAM !!!!

我改编的文件

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

在食谱中阅读有关此内容的更多信息:

答案 2 :(得分:0)

您可以尝试。希望它能对您有所帮助

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