我知道还有其他方法可以实现此目的,但是我想通过initState()使用Future来使用SharedPreferences获得List而不使用await。以下内容说明了我要实现的目标,并且确实有效。因为我以前从未使用过这种模式,所以我不确定这是否是最好的方法(不使用await)。有没有不用等待的更好的方法吗?
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class _MyHomePageState extends State<MyHomePage> {
SharedPreferences _prefs;
String _sMessage1;
String _sMessage2;
List<String> _lsCategories;
@override
void initState() {
super.initState();
Future<void> future = _initPreferences();
future.then((_) {
if (_prefs != null) {
try {
_lsCategories = _prefs.getStringList("categories") ?? [];
debugPrint("Categories = $_lsCategories");
_sMessage2 = "Categories loaded OK";
} catch (vError) {
_sMessage2 = ("Error loading categories = $vError");
}
}
setState(() {});
});
}
Future<void> _initPreferences() {
return SharedPreferences.getInstance().then((prefs) {
_prefs = prefs;
_sMessage1 = "Preferences initialized OK";
}).catchError((vError) {
_sMessage1 = "Error initializing preferences = ${vError.toString()}";
_sMessage2 = "Unable to load categories";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_createText(_sMessage1),
SizedBox(height: 20),
_createText(_sMessage2),
],
),
),
);
}
}
Text _createText(String sText) {
return Text(sText == null ? "" : sText,
style: TextStyle(
color: Colors.red[500], fontWeight: FontWeight.bold, fontSize: 20));
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Future Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "Flutter Future Test"),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
答案 0 :(得分:0)
就异步而言,您所做的工作很好。但是,它太冗长了。例如,您不需要通过状态传输prefs实例。
另一项改进可能是检查完成Future
后是否仍挂载了窗口小部件。 (如果使用FutureBuilder
,则不必为此担心。)
您的代码有一个问题,就是您要在setState()
之外设置状态变量。不能保证那样做得很好,我发誓我有时会使用旧状态。您应该在setState()
以下是我想编码的几种不同方式:
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then((prefs) {
if(!mounted) return;
setState(() {
_prefs = prefs;
_lsCategories = _prefs.getStringList("categories") ?? [];
debugPrint("Categories = $_lsCategories");
_sMessage2 = "Categories loaded OK";
});
}).catchError((vError) {
setState(() {
_sMessage2 = ("Error loading categories = $vError");
});
});
}
@override
void initState() {
super.initState();
_initPreferences();
}
Future<void> _initPreferences() async {
final prefs = await SharedPreferences.getInstance();
if (!mounted) return;
setState(() {
try {
_prefs = prefs;
_lsCategories = _prefs.getStringList("categories") ?? [];
debugPrint("Categories = $_lsCategories");
_sMessage2 = "Categories loaded OK";
} catch (vError) {
_sMessage2 = ("Error loading categories = $vError");
}
});
}