Flutter Flatter应用程序在首次启动时未立即从共享首选项获取数据
我有一个名为Flutter Flatter应用程序在首次启动时未立即从共享首选项获取数据,flutter,dart,sharedpreferences,Flutter,Dart,Sharedpreferences,我有一个名为highScore的字段,它的数据保存在共享首选项中,我想重新记录它的数据并显示在应用程序首次启动时显示的first\u页面中,但在第一次启动时,它只显示null,我必须转到quick\u页面,然后返回以获取数据,即使我尝试从initState()加载数据 银行问题 class QuestionBank { static final QuestionBank _questionBank = QuestionBank._internal(); factory Ques
highScore
的字段,它的数据保存在共享首选项中,我想重新记录它的数据并显示在应用程序首次启动时显示的first\u页面中,但在第一次启动时,它只显示null,我必须转到quick\u页面
,然后返回以获取数据,即使我尝试从initState()
加载数据
银行问题
class QuestionBank {
static final QuestionBank _questionBank = QuestionBank._internal();
factory QuestionBank() {
return _questionBank;
}
QuestionBank._internal();
int _questionNumber = 0;
int _score = 0;
int highScore;
incrementCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
highScore = (prefs.getInt('counter') ?? 0) + 1;
prefs.setInt('counter', highScore);
}
loadCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
highScore = (prefs.getInt('counter') ?? 0);
}
int getScore() => _score;
int getLength() => _questionList.length;
}
第一页
class FirstPage extends StatefulWidget {
@override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
QuestionBank questionBank;
@override
void initState() {
super.initState();
questionBank = QuestionBank();
questionBank.loadCounter();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white24,
body: Padding(
padding: const EdgeInsets.only(top: 40),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
'High Score: ${questionBank.highScore}',
style: titleStyle,
),
SizedBox(
height: 76,
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: Image(
image: AssetImage(
'images/logoDesigne7crop.png',
),
),
),
SizedBox(
height: 30,
),
Container(
height: 70,
width: double.infinity,
margin: EdgeInsets.all(10),
child: ChoiceButton(
btnText: 'start the quiz',
tap: () {
Navigator.of(context).pushNamed(startQuizRoute);
}),
),
Container(
height: 70,
margin: EdgeInsets.all(10),
width: double.infinity,
child: ChoiceButton(
btnText: 'search',
tap: () {
Navigator.of(context).pushNamed(searchRoute);
})),
],
),
),
),
);
}
}
class QuizPage extends StatefulWidget {
@override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage>
with SingleTickerProviderStateMixin {
QuestionBank questionBank = QuestionBank();
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 14, right: 8, left: 6),
child: TopRow(questionBank: questionBank),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Center(
child: Text(questionBank.getQuestionTitle(),
textAlign: TextAlign.center, style: titleStyle),
),
Padding(
padding: const EdgeInsets.only(top: 30, bottom: 20),
child: Image.asset(
questionBank.getQuestionImage(),
height: 180,
),
),
SizedBox(
height: 76,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0, vertical: 5),
child: ChoiceButton(
btnText: 'Fruit',
tap: () {
setState(() {
questionBank.bigCheck(1);
});
},
),
),
),
SizedBox(
height: 76,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0, vertical: 5),
child: ChoiceButton(
btnText: 'Vegetable',
tap: () {
setState(() {
questionBank.bigCheck(2);
});
},
),
),
),
SizedBox(
height: 76,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0, vertical: 5),
child: ChoiceButton(
btnText: 'Fungus',
tap: () {
setState(() {
questionBank.bigCheck(3);
});
},
),
),
),
SizedBox(
height: 76,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0, vertical: 5),
child: ChoiceButton(
btnText: 'Berry',
tap: () {
setState(() {
questionBank.bigCheck(4);
});
},
),
),
),
],
),
),
],
),
),
);
}
}
class TopRow extends StatelessWidget {
const TopRow({
Key key,
@required this.questionBank,
}) : super(key: key);
final QuestionBank questionBank;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'High Score: ${questionBank.highScore}',
style: TextStyle(fontSize: 25, color: Colors.white),
),
SizedBox(
height: 10,
),
Row(
children: <Widget>[
Text(
'Score: ${questionBank.getScore()}',
style: TextStyle(fontSize: 25, color: Colors.white),
),
SizedBox(
width: 220,
),
Icon(
FontAwesome.heart,
size: 26,
),
Icon(
Icons.audiotrack,
size: 26,
),
],
)
],
);
}
}
questionBank.loadCounter()
是一个同步任务,这意味着它需要时间,线程将通过此点
现在,您可以选择等待并显示某些内容,直到加载为止
为此,您可以将FutureBuilder
与future:questionBank.loadCounter()一起使用
阅读
根据评论中的讨论创建一个类
class AppConstant {
static QuestionBank questionBank=QuestionBank();
}
现在在调用run调用loadCounter之前
void main() {
await AppConstant.questionBank.loadCounter();
runApp(MyApp());
}
现在不是在状态中初始化问题库。直接使用AppConstant.questionBank
检查FutureBuilder
类文档谢谢,但我不希望在加载数据时显示其他小部件,我希望数据立即显示。“我希望数据立即显示”,你不能这样做-如果你的函数返回Future
你不能“立即”得到它-只需使用FutureBuilder
-官方文档有一些基本的数据,但我不能将这些数据缓存到某个地方,以便下次启动应用程序时可以使用吗?当然可以(例如),但你为什么要使用“共享首选项”然后呢?但是我想在应用程序运行的第二秒显示值,而不是显示另一个小部件,有没有一种方法可以像缓存它这样做呢代码>在静态类中,然后在runApp调用之前等待questionBank.loadCounter()代码>你能解释一下吗,我对异步编程了解不多,现在我只想完成这个应用程序。我这么做了,但这使我的应用程序无法启动,冻结在白色屏幕上!有什么错误吗?更好地实现一个启动屏幕,您将在其中执行此操作。实际上,如果不理解异步的东西,这将是很困难的。只要记住,无论何时访问卡、网络或任何东西,您都会得到异步响应,现在取决于您如何调整ui中经过的时间。