【问题标题】:Why MaterialApp is not loading after successful auth?为什么在成功验证后 MaterialApp 没有加载?
【发布时间】:2021-08-05 21:43:09
【问题描述】:

我是 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

main.dart:

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

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

【问题讨论】:

  • 因为您的代码没有将请求重定向到主路径(“/”)。另外,我很确定你在这里错过了一个 await _authService.signIn(_email, _password);
  • @vincenzopalazzo 你的意思是我应该在 _authService.signIn() 之后重定向,也许用导航器?
  • 关于签名成功。 Flutter 不知道何时显示 Home View,但只知道当您需要像“/”这样的路径时要返回的视图是什么。
  • 我必须说,这行得通:await _authService.signIn(_email, _password); Navigator.pushNamed(context, '/');
  • 我下面的回答还包括错误登录。 StreamProvider 只是一个地图 在显示此视图时您没有放置任何信息。这就像过去 10 年的所有框架一样。使用中介模式

标签: flutter dart


【解决方案1】:

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

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

下面的代码可以解决你的问题。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 2020-10-16
    • 2022-12-01
    相关资源
    最近更新 更多