颤动:共享偏好问题
flutter : shared preference issue
我正在尝试向我的应用程序添加一个共享首选项以保存用户的数据以供下次登录,但是我收到一个错误并且我有一个加载数据的无限循环并且我的应用程序在这个循环之后崩溃了。
这是我得到的错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception:
setState() called after dispose(): _SplashScreenState#e691a(lifecycle
state: defunct, not mounted) E/flutter ( 2799): This error happens if
you call setState() on a State object for a widget that no longer
appears in the widget tree (e.g., whose parent widget no longer
includes the widget in its build). This error can occur when code
calls setState() from a timer or an animation callback. E/flutter (
2799): The preferred solution is to cancel the timer or stop listening
to the animation in the dispose() callback. Another solution is to
check the "mounted" property of this object before calling setState()
to ensure the object is still in the tree. E/flutter ( 2799): This
error might indicate a memory leak if setState() is being called
because another object is retaining a reference to this State object
after it has been removed from the tree. To avoid memory leaks,
consider breaking the reference to this object during dispose().
这是在我的启动画面中获得偏好的方法
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isLog = prefs.getBool("islog");
print(this.mounted);
if(this.mounted){
if (isLog == true) {
setState(() {
String email = prefs.getString("email");
String pass = prefs.getString("pass");
signIn(email, pass);
});
}
}else {
if(!mounted)
setState(() {
isLoading = false;
});
}
}
signIn(String email, String pass) async {
var res = await userProvider.login(email, pass);
var user = userProvider.user.tourist;
if (res is FailedRequest) {
Dialogs.showErrorDialog(context, message: res.message, code: res.code);
} else if (user == true) {
print("Shared ***********************************************");
await appProvider.countryList();
await appProvider.activityList();
await appProvider.tourGuideList();
setState(() {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => BottomTourist()));
});
}
这是我的闪屏小部件
@override
Widget build(BuildContext context) {
userProvider = Provider.of<UserProvider>(context, listen: false);
appProvider = Provider.of<AppProvider>(context, listen: false);
init();
return Container(
child: Scaffold(
body: Stack(
children: <Widget>[
Container(
foregroundDecoration: !AppTheme.isLightTheme
? BoxDecoration(
color:
AppTheme.getTheme().backgroundColor.withOpacity(0.4))
: null,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Image.asset('assets/images/introduction.jpg',
fit: BoxFit.cover),
),
Column(
children: <Widget>[
Expanded(
flex: 1,
child: SizedBox(),
),
Center(
child: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
offset: Offset(1.1, 1.1),
blurRadius: 10.0),
],
),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
child: Image.asset('assets/images/appIcon.png'),
),
),
),
SizedBox(
height: 16,
),
Expanded(
flex: 4,
child: SizedBox(),
),
Padding(
padding: const EdgeInsets.only(
left: 48, right: 48, bottom: 8, top: 8),
child: Container(
height: 48,
decoration: BoxDecoration(
color: AppTheme.getTheme().primaryColor,
borderRadius: BorderRadius.all(Radius.circular(24.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
blurRadius: 8,
offset: Offset(4, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(24.0)),
highlightColor: Colors.transparent,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => IntroductionScreen()),
);
},
child: Center(
child: Text(
"Get started",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.white),
),
),
),
),
),
),
],
),
],
),
),
);
}
}
这是我的登录方法,用于为用户设置首选项
signIn() async {
var res = await userProvider.login(
_userNameController.text, _passwordController.text);
var user = userProvider.user.tourist;
SharedPreferences prefs = await SharedPreferences.getInstance();
if (res is FailedRequest) {
Dialogs.showErrorDialog(context, message: res.message, code: res.code);
} else if (user == true) {
print("Signing in success");
await appProvider.countryList();
await appProvider.activityList();
await appProvider.tourGuideList();
setState(() {
prefs.setBool("islog", true);
prefs.setString('pass', userProvider.user.password);
prefs.setString('email', userProvider.user.email);
Navigator.pushReplacement(widget._context,
MaterialPageRoute(builder: (context) => BottomTourist()));
});
}
所以有人可以帮我解决我的问题吗?
我正在尝试向我的应用程序添加一个共享首选项以保存用户的数据以供下次登录,但是我收到一个错误并且我有一个加载数据的无限循环并且我的应用程序在这个循环之后崩溃了。
这是我得到的错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: setState() called after dispose(): _SplashScreenState#e691a(lifecycle state: defunct, not mounted) E/flutter ( 2799): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. E/flutter ( 2799): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree. E/flutter ( 2799): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
这是在我的启动画面中获得偏好的方法
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isLog = prefs.getBool("islog");
print(this.mounted);
if(this.mounted){
if (isLog == true) {
setState(() {
String email = prefs.getString("email");
String pass = prefs.getString("pass");
signIn(email, pass);
});
}
}else {
if(!mounted)
setState(() {
isLoading = false;
});
}
}
signIn(String email, String pass) async {
var res = await userProvider.login(email, pass);
var user = userProvider.user.tourist;
if (res is FailedRequest) {
Dialogs.showErrorDialog(context, message: res.message, code: res.code);
} else if (user == true) {
print("Shared ***********************************************");
await appProvider.countryList();
await appProvider.activityList();
await appProvider.tourGuideList();
setState(() {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => BottomTourist()));
});
}
这是我的闪屏小部件
@override
Widget build(BuildContext context) {
userProvider = Provider.of<UserProvider>(context, listen: false);
appProvider = Provider.of<AppProvider>(context, listen: false);
init();
return Container(
child: Scaffold(
body: Stack(
children: <Widget>[
Container(
foregroundDecoration: !AppTheme.isLightTheme
? BoxDecoration(
color:
AppTheme.getTheme().backgroundColor.withOpacity(0.4))
: null,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Image.asset('assets/images/introduction.jpg',
fit: BoxFit.cover),
),
Column(
children: <Widget>[
Expanded(
flex: 1,
child: SizedBox(),
),
Center(
child: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
offset: Offset(1.1, 1.1),
blurRadius: 10.0),
],
),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
child: Image.asset('assets/images/appIcon.png'),
),
),
),
SizedBox(
height: 16,
),
Expanded(
flex: 4,
child: SizedBox(),
),
Padding(
padding: const EdgeInsets.only(
left: 48, right: 48, bottom: 8, top: 8),
child: Container(
height: 48,
decoration: BoxDecoration(
color: AppTheme.getTheme().primaryColor,
borderRadius: BorderRadius.all(Radius.circular(24.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
blurRadius: 8,
offset: Offset(4, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(24.0)),
highlightColor: Colors.transparent,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => IntroductionScreen()),
);
},
child: Center(
child: Text(
"Get started",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.white),
),
),
),
),
),
),
],
),
],
),
),
);
}
}
这是我的登录方法,用于为用户设置首选项
signIn() async {
var res = await userProvider.login(
_userNameController.text, _passwordController.text);
var user = userProvider.user.tourist;
SharedPreferences prefs = await SharedPreferences.getInstance();
if (res is FailedRequest) {
Dialogs.showErrorDialog(context, message: res.message, code: res.code);
} else if (user == true) {
print("Signing in success");
await appProvider.countryList();
await appProvider.activityList();
await appProvider.tourGuideList();
setState(() {
prefs.setBool("islog", true);
prefs.setString('pass', userProvider.user.password);
prefs.setString('email', userProvider.user.email);
Navigator.pushReplacement(widget._context,
MaterialPageRoute(builder: (context) => BottomTourist()));
});
}
所以有人可以帮我解决我的问题吗?