【发布时间】: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 年的所有框架一样。使用中介模式