已解决:Flutter Provider:改变屏幕上的数据消失
SOLVED: Flutter Provider: Disappearing data on changing screen
我用过几次 flutter 'provider' 包都没有问题,但现在我遇到了问题。
登录时,我从 Firebase 数据库获取用户角色,并通过 [=49= 更改我的 UserProvider class(由 ChangeNotifier 扩展)的 'role' 属性 ] 函数。
在导航到主屏幕时,我尝试使用 'getRole' 函数从 UserProvider 获取值,但它是一个空字符串。不知何故,改变屏幕我失去了价值。
我试过在更改角色和获取时打印值,我可以确认我更改了值,但不知何故在更改屏幕后它丢失了。
代码的相关部分如下:
user_provider.dart
import 'package:flutter/cupertino.dart';
class UserProvider with ChangeNotifier {
String _role = '';
void changeRole(String newRole) {
_role = newRole;
print('CHANGEROLE: $_role'); // print statements added just for trying to solve this problem
notifyListeners();
}
String get getRole {
print('GETROLE: $_role');
return _role;
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
ChangeNotifierProvider(
create: (context) => UserProvider(),
child: MyApp(),
),
);
}
...
服务上的登录功能
void login() async {
try {
UserCredential userCredential = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
var data = await FirebaseFirestore.instance.collection('users').where('uid', isEqualTo: userCredential.user.uid).get();
UserProvider().changeRole(data.docs[0]['role']);
Navigator.of(context).pushNamed(MainScreen.routeName);
...
这里是它应该显示的地方:
main_screen.dart
...
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Consumer<UserProvider>(
builder: (context, user, child) {
return Text('This is your role: ${user.getRole}');
},
),
...
尽管如此,我得到一个空字符串,因为它没有被更改。 UserProvider 模型上的打印确认:
I/flutter (23760): CHANGEROLE: megauser
I/flutter (23760): GETROLE:
如您所见,我正在更改角色,但 getter returns 是一个空字符串。我做错了什么?
编辑:感谢 Sifat Amin 指出解决方案。只需将“_role”参数设置为 'static' 即可。
像这样创建您的应用程序
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
],
child: MyApp(),
),
);
添加此行并运行您的 UserProvider
class
String get role => _role;
void changeRole(String newRole){
_role = newRole;
notifyListeners();
}
并像这样更改登录屏幕中的角色
context.read<UserProvider>().changeRole(newRole);
并在所有小部件中像这样访问它
context.read<UserProvider>().role;
我想将 _role 更改为静态就足够了。由于您每次都在创建一个新实例,因此数据会丢失。将 _role 声明为静态就足够了
static String role ;
所以你根本不需要 get 方法。我认为它应该有效
我用过几次 flutter 'provider' 包都没有问题,但现在我遇到了问题。
登录时,我从 Firebase 数据库获取用户角色,并通过 [=49= 更改我的 UserProvider class(由 ChangeNotifier 扩展)的 'role' 属性 ] 函数。
在导航到主屏幕时,我尝试使用 'getRole' 函数从 UserProvider 获取值,但它是一个空字符串。不知何故,改变屏幕我失去了价值。
我试过在更改角色和获取时打印值,我可以确认我更改了值,但不知何故在更改屏幕后它丢失了。
代码的相关部分如下:
user_provider.dart
import 'package:flutter/cupertino.dart';
class UserProvider with ChangeNotifier {
String _role = '';
void changeRole(String newRole) {
_role = newRole;
print('CHANGEROLE: $_role'); // print statements added just for trying to solve this problem
notifyListeners();
}
String get getRole {
print('GETROLE: $_role');
return _role;
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
ChangeNotifierProvider(
create: (context) => UserProvider(),
child: MyApp(),
),
);
}
...
服务上的登录功能
void login() async {
try {
UserCredential userCredential = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
var data = await FirebaseFirestore.instance.collection('users').where('uid', isEqualTo: userCredential.user.uid).get();
UserProvider().changeRole(data.docs[0]['role']);
Navigator.of(context).pushNamed(MainScreen.routeName);
...
这里是它应该显示的地方: main_screen.dart
...
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Consumer<UserProvider>(
builder: (context, user, child) {
return Text('This is your role: ${user.getRole}');
},
),
...
尽管如此,我得到一个空字符串,因为它没有被更改。 UserProvider 模型上的打印确认:
I/flutter (23760): CHANGEROLE: megauser
I/flutter (23760): GETROLE:
如您所见,我正在更改角色,但 getter returns 是一个空字符串。我做错了什么?
编辑:感谢 Sifat Amin 指出解决方案。只需将“_role”参数设置为 'static' 即可。
像这样创建您的应用程序
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
],
child: MyApp(),
),
);
添加此行并运行您的 UserProvider
class
String get role => _role;
void changeRole(String newRole){
_role = newRole;
notifyListeners();
}
并像这样更改登录屏幕中的角色
context.read<UserProvider>().changeRole(newRole);
并在所有小部件中像这样访问它
context.read<UserProvider>().role;
我想将 _role 更改为静态就足够了。由于您每次都在创建一个新实例,因此数据会丢失。将 _role 声明为静态就足够了
static String role ;
所以你根本不需要 get 方法。我认为它应该有效