flutter - 为什么在成功验证后 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();
}
}
解决方案
您在 onPress 事件中以错误的方式使用异步功能。
另一个问题是您在登录失败的情况下错过了错误,并在登录成功的情况下重定向呼叫。
以下代码可以成为解决您问题的解决方案。
onPressed: () {
_authService.signIn().then((userModel) {
Navigator.pushNamed(context, "/");
}).catchError(() => print("not able to be reached"));
在您的代码中有两个问题,您永远不会在主路径中重定向请求视图"/"
。你永远不会等待异步函数_authService.signIn()
推荐阅读
- javascript - 模拟来自同一类的承诺返回方法
- ida - ida pro idc 脚本问题我无法解决任何想法?
- jenkins - 如何将 jenkins 管道中的 Jenkins 配置文件复制到 Web 服务器
- php - 使用 .htaccess 隐藏文件夹的文件扩展名
- java - 使用 Spring Boot 和 H2 运行测试时出现异常“无法加载 ApplicationContext”
- xml - 将简单 XML 导入 Power BI
- r - 如何将特定行转换为r中的列?
- php - PHP 使用 foreach 遍历 JSON
- javascript - 根据匹配的键/值属性过滤对象数组?
- mongodb - Grails 3 使用 _id 和 id 保存 mongoDB 文档