Flutter 颤振:SharedReferences在应用程序启动时未获取值
我正在尝试存储一个值,并基于要导航到LandinPage或HomePage的值。但是,当我的应用程序加载时,我无法获取SharedReferences值。当前,该值是在单击登录页中的按钮时以及在我关闭/最小化应用程序时设置的。我甚至看不到main.dart的打印消息,也无法获取值。我做错了什么 这是我的密码:Flutter 颤振:SharedReferences在应用程序启动时未获取值,flutter,Flutter,我正在尝试存储一个值,并基于要导航到LandinPage或HomePage的值。但是,当我的应用程序加载时,我无法获取SharedReferences值。当前,该值是在单击登录页中的按钮时以及在我关闭/最小化应用程序时设置的。我甚至看不到main.dart的打印消息,也无法获取值。我做错了什么 这是我的密码: import 'package:credit/src/pages/landing.dart'; import 'package:flutter/material.dart'; import
import 'package:credit/src/pages/landing.dart';
import 'package:flutter/material.dart';
import 'package:credit/src/pages/credit/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
_LoadingPageState createState() => _LoadingPageState();
}
class _LoadingPageState extends State<MyApp> {
@override
void initState() {
super.initState();
getUserStatus().then((userStatus) {
if (userStatus == null) {
Navigator.of(context)
.push(MaterialPageRoute<Null>(builder: (BuildContext context) {
return LandingPage();
}));
} else {
Navigator.of(context)
.push(MaterialPageRoute<Null>(builder: (BuildContext context) {
return HomePage();
}));
}
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: CircularProgressIndicator(),
));
}
}
Future<String> getUserStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String userStatus = prefs.getString('userstatus');
print("==On Load Check ==");
print(userStatus);
return userStatus;
}
您已声明MyApp的main方法,但从未调用它。启动应用程序的主应用程序中包含runApp。您可以将prefs.getString移动到真正的main中,使其异步,然后将该值作为参数传递到MyApp小部件。您已经声明了MyApp的方法main,但从未调用它。启动应用程序的主应用程序中包含runApp。您可以将prefs.getString移动到真正的main中,使其异步,然后将该值作为参数传递到MyApp小部件中。您可能需要使用在两个页面中的任何一个之前首先加载的加载页面:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'An App',
home: LoadingPage(),
routes: {
'/landing': (context) => LandingPage(),
'/home': (context) => HomePage(),
}
);
}
}
class LoadingPage extends StatefulWidget {
LoadingPage({Key key}) : super(key: key);
_LoadingPageState createState() => _LoadingPageState();
}
class _LoadingPageState extends State<LoadingPage> {
@override
void initState() {
super.initState();
loadPage();
}
loadPage() {
getUserStatus().then((userStatus) {
if (userStatus == null) {
Navigator.of(context).pushNamed('/landing');
} else {
Navigator.of(context).pushNamed('/home');
}
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: CircularProgressIndicator(),
));
}
}
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Home Page'),
);
}
}
class LandingPage extends StatefulWidget {
LandingPage({Key key}) : super(key: key);
_LandingPageState createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage> {
@override
void initState() {
super.initState();
setUserStatus('done');
}
@override
Widget build(BuildContext context) {
return Container(
child: Text('Landing'),
);
}
}
Future<String> getUserStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String userStatus = prefs.getString('userStatus');
print("==On Load Check ==");
print(userStatus);
return userStatus;
}
Future<bool> setUserStatus(String userStatus) async{
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('userStatus', userStatus);
return true;
}
您可能需要先使用加载页面,然后再加载两个页面中的任何一个:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'An App',
home: LoadingPage(),
routes: {
'/landing': (context) => LandingPage(),
'/home': (context) => HomePage(),
}
);
}
}
class LoadingPage extends StatefulWidget {
LoadingPage({Key key}) : super(key: key);
_LoadingPageState createState() => _LoadingPageState();
}
class _LoadingPageState extends State<LoadingPage> {
@override
void initState() {
super.initState();
loadPage();
}
loadPage() {
getUserStatus().then((userStatus) {
if (userStatus == null) {
Navigator.of(context).pushNamed('/landing');
} else {
Navigator.of(context).pushNamed('/home');
}
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: CircularProgressIndicator(),
));
}
}
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Home Page'),
);
}
}
class LandingPage extends StatefulWidget {
LandingPage({Key key}) : super(key: key);
_LandingPageState createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage> {
@override
void initState() {
super.initState();
setUserStatus('done');
}
@override
Widget build(BuildContext context) {
return Container(
child: Text('Landing'),
);
}
}
Future<String> getUserStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String userStatus = prefs.getString('userStatus');
print("==On Load Check ==");
print(userStatus);
return userStatus;
}
Future<bool> setUserStatus(String userStatus) async{
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('userStatus', userStatus);
return true;
}
我觉得威利的答案可能同样好,但这里有另一种方法 总的来说,我的方法是自动加载主主页,然后在主页的初始状态下,检查这是否是用户第一次访问应用程序。如果是这样,请立即将登录页弹出顶部。我成功地使用了这种方法,用户体验不好 下面是默认应用程序,但您的SharedReferences代码已移动到相应位置
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
var userStatus;
//If user status is null, then show landing page.
Future<void> checkUserStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
userStatus = prefs.getString('userstatus');
print("==On Load Check ==");
print(userStatus);
if (userStatus == null) {
Navigator.push(context, MaterialPageRoute(builder: (context) => LandingPage()));
}
}
@override
void initState() {
super.initState();
//Call check for landing page in init state of your home page widget
checkUserStatus();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class LandingPage extends StatefulWidget {
@override
_LandingPageState createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage> {
@override
Widget build(BuildContext context) {
//Build landing page here.
return Container();
}
}
我觉得威利的答案可能同样好,但这里有另一种方法 总的来说,我的方法是自动加载主主页,然后在主页的初始状态下,检查这是否是用户第一次访问应用程序。如果是这样,请立即将登录页弹出顶部。我成功地使用了这种方法,用户体验不好 下面是默认应用程序,但您的SharedReferences代码已移动到相应位置
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
var userStatus;
//If user status is null, then show landing page.
Future<void> checkUserStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
userStatus = prefs.getString('userstatus');
print("==On Load Check ==");
print(userStatus);
if (userStatus == null) {
Navigator.push(context, MaterialPageRoute(builder: (context) => LandingPage()));
}
}
@override
void initState() {
super.initState();
//Call check for landing page in init state of your home page widget
checkUserStatus();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class LandingPage extends StatefulWidget {
@override
_LandingPageState createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage> {
@override
Widget build(BuildContext context) {
//Build landing page here.
return Container();
}
}
谢谢你,埃里克,我也想过同样的方法,但是我想它会不会引起瞬间的闪烁?或者在重新定向到登录页之前浏览主页。不过我会尝试一下。谢谢你,埃里克,我也想过同样的方法,但我还是忍不住想,它会不会引起瞬间的闪烁?或者在重新定向到登录页之前浏览主页。我将尝试一下。我厌倦了使用相同的方法,但是,我得到了一个错误,它表示使用不包含导航器的上下文请求导航器操作。E/Flatter 8838:用于从导航器推送或弹出路由的上下文必须是导航器小部件的后代,我相信它没有获得正确的上下文,我已经更新了原始代码。知道为什么吗?我已经编辑了代码,使之成为一个完整的运行示例。只需复制、粘贴和编辑到您喜欢的位置。我通常使用命名路由,但你可以编辑它,看看它是否与路由生成器一起工作。@willienadi当我从登录页按后退按钮时,一个圆圈正在旋转,如何直接退出应用程序。但是,我厌倦了使用相同的方法,我得到一个错误,该错误表示请求的导航器操作的上下文不包括导航器。E/Flatter 8838:用于从导航器推送或弹出路由的上下文必须是导航器小部件的后代,我相信它没有获得正确的上下文,我已经更新了原始代码。知道为什么吗?我已经编辑了代码,使之成为一个完整的运行示例。只需复制、粘贴和编辑到您喜欢的位置。我通常使用命名路由,但您可以编辑它,并查看它是否与路由生成器一起工作。@willienadi当我从登录页按“后退”按钮时,一个圆圈正在旋转,如何直接退出应用程序。