首页 > 解决方案 > 为什么在成功验证后 MaterialApp 没有加载?

问题描述

我是 Flutter 的新手,尝试使用健全的 null 安全性,但我无法弄清楚为什么 Home() 小部件从未出现过。用户不能越过登录屏幕。

我使用 StreamProvider 通知 Wrapper() 小部件有关经过身份验证的用户的更改。当 user.id 不同于空字符串时, Wrapper() 应该返回一个 MaterialApp() 显然永远不会显示。

我尝试使用 print() 进行调试,它显示 user.id 有一个值,但仅此而已。

我可能首先使用了一种整体错误的方法,因为我正在调整从教程中获取的一些非空安全代码......但是在这一点上(从学习的角度来看)我也很想知道如何调试它。

这是应用程序启动时的调试控制台输出

>>>>>>> main: start
MyApp: start
MyApp: still waiting...
Wrapper: start
MyApp: Error with  StreamProvider<UserModel>
MyApp: Error is : Unexpected null value.
Wrapper: start

这是成功登录尝试后发生的情况:

AuthService: signing in with email and password
AuthService: waiting for signInWithEmailAndPassword
Debug: AuthService wait finished. Userid ANDxpHh85let0fEM1WYGut3vFZG2
Wrapper: start
Wrapper: user.id: ANDxpHh85let0fEM1WYGut3vFZG2

主要飞镖:

void main() {
  print(">>>>>>> main: start");
  WidgetsFlutterBinding.ensureInitialized();
  runApp(Cocco());
}

class Cocco extends StatelessWidget {
  final Future<FirebaseApp> _firebaseInit = Firebase.initializeApp();

  @override
  Widget build(BuildContext context) {
    print('MyApp: start');
    return FutureBuilder(
      future: _firebaseInit,
      builder: (context, initResult) {
        if (initResult.hasError) {
          print("MyApp: error initialising Firebase");
          return ErrorScreen(text: initResult.error.toString());
        }
        if (initResult.connectionState == ConnectionState.done) {
          return StreamProvider<UserModel>.value(
            value: AuthService().user,
            initialData: UserModel(''),
            catchError: (context, err) {
              print('MyApp: Error with  StreamProvider<UserModel>');
              print('MyApp: Error is : ' + err.toString());
              return UserModel('');
            },
            child: Container(
              child: MaterialApp(
                home: Wrapper(),
              ),
            ),
          );
        }

        // Show spinner if future is still uncertain
        print("MyApp: still waiting...");
        return Loading();
      },
    );
  }
}

这是我的 wrapper.dart

class Wrapper extends StatelessWidget {
  const Wrapper({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('Wrapper: start');

    final user = Provider.of<UserModel>(context);

    // If user has no id, then load auth routes
    if (user.id == '') {
      return MaterialApp(
        initialRoute: '/signin',
        routes: {
          '/signin': (context) => SignIn(),
          '/signup': (context) => SignUp(),
        },
      );
    }

    print('Wrapper: user.id: ' + user.id);
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => Home(),
        '/addAssessment': (context) => T4CAssessment(),
      },
    );
  }
}

登录.dart

class SignIn extends StatefulWidget {
  SignIn({Key? key}) : super(key: key);

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

class _SignInState extends State<SignIn> {
  AuthService _authService = AuthService();
  String _email = '';
  String _password = '';

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: Text("Accedi"),
        ),
        body: Form(
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
            child: Column(
              children: <Widget>[
                TextFormField(
                  decoration: InputDecoration(
                    hintText: 'email',
                  ),
                  textCapitalization: TextCapitalization.none,
                  onChanged: (val) => setState(() {
                    _email = val;
                  }),
                ),
                TextFormField(
                  decoration: InputDecoration(
                    hintText: 'password',
                  ),
                  obscureText: true,
                  onChanged: (val) => setState(() {
                    _password = val;
                  }),
                ),
                Padding(
                  padding: EdgeInsets.symmetric(vertical: 16.0),
                  child: ElevatedButton(
                    onPressed: () async {
                      _authService.signIn(_email, _password);
                    },
                    child: Text('Accedi'),
                  ),
                ),
                Spacer(),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text('Non hai ancora account? '),
                    TextButton(
                      onPressed: () {
                        Navigator.pushReplacementNamed(context, '/signup');
                      },
                      child: Text('Registrati!'),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

服务/auth.dart

class AuthService {
  FirebaseAuth _auth = FirebaseAuth.instance;

  UserModel _userFromFirabase(User user) {
    return UserModel(user.uid);
  }

  Stream<UserModel> get user {
    return _auth.authStateChanges().map((user) => _userFromFirabase(user!));
  }

  Future<UserModel?> signIn(String email, String password) async {
    print('AuthService: signing in with email and passwrod');
    try {
      print('AuthService: waiting for signInWithEmailAndPassword');

      UserCredential userCred = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
      print('Debug: AuthService wait finished. Userid ' + userCred.user!.uid);
      return _userFromFirabase(userCred.user!);
    } catch (e) {
      print(e);
      print('Debug: AuthService wait finished.');
      return null;
    }
  }

  Future<void> signOut() async {
    await _auth.signOut();
  }
}

标签: flutterdart

解决方案


您在 onPress 事件中以错误的方式使用异步功能。

另一个问题是您在登录失败的情况下错过了错误,并在登录成功的情况下重定向呼叫。

以下代码可以成为解决您问题的解决方案。

  onPressed: () {
    _authService.signIn().then((userModel) {
          Navigator.pushNamed(context, "/");
    }).catchError(() => print("not able to be reached"));

在您的代码中有两个问题,您永远不会在主路径中重定向请求视图"/"。你永远不会等待异步函数_authService.signIn()


推荐阅读