dart - 保存和加载,共享首选项
问题描述
List<double> timersValuesList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
void saveSharedPreferences() async {
// from List of double to a List of String
List<String> convertedTimerValues = timersValuesList.map((i) => i.toString()).toList();
// getting the instance of sharedPreferences as Object prefs
SharedPreferences prefs = await SharedPreferences.getInstance();
// taking my List as key of "mylist", if it doesn't exist create empty List, this is List of String
List<String> myList = (prefs.getStringList('mylist') ?? List<String>());
//saving the List of String as key"mylist"
await prefs.setStringList('mylist', convertedTimerValues);
}
void loadSharedPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> myList = (prefs.getStringList('mylist') ?? List<String>());
List<double> myOriginalList = myList.map((i)=> double.parse(i)).toList();
timersValuesList = myOriginalList;
// print('Your list $myOriginalList');
}
我尝试在此文件中使用 SharedPreferences 来保存和加载 6 个双精度值的列表,这些值在其他小部件中使用并且可以修改。现在的问题是,每次我打开我的应用程序时,它不会让我看到更新和修改的值,但总是第一个我声明为默认值。例如。我编辑了我的第一个值,它变成了这样。
timersValuesList[0] = 35
然后我保存它并退出应用程序。当我重新启动应用程序时,它显示的值是 30 而不是 35,就像它应该的那样。但是,如果我使用 +1 进行编辑,它会直接跳到 36,所以这让我觉得值已保存但在第一次启动时没有正确显示。之后,添加值可以正常工作。有人能帮我吗?我找不到办法做到这一点。也许我应该在保存功能中输入默认值,以防不存在任何已保存的文件?感谢有关保存和加载双重列表的代码的帮助,因为我认为我做得不好。再次感谢。
我做的。(我可以在 initState 中调用任何异步函数,所以我调用了外部函数)。但我收到错误:“NoSuchMethodError:方法“[]”在 null 上被调用。接收方:null 尝试调用:“
class _SettingsPageState extends State<SettingsPage> {
List<double> timersList;
@override initState() {
super.initState();
callLoad();
}
Future callLoad() async {
timersList = await loadTimers();
}
void saveTimers(List<double> timersList) async {
List<String> convertedTimerValues = timersList.map((i) => i.toString()).toList();
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setStringList('TimerList', convertedTimerValues);
}
Future<List<double>> loadTimers() async {
List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
List<double> savedTimerList;
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> myList = prefs.getStringList('TimerList');
if (myList == null ){
return defaultTimersList;
} else{
savedTimerList = myList.map((i)=> double.parse(i)).toList();
return savedTimerList;
}
}
我按照您的代码建议进行编辑。但我收到此错误,但屏幕已加载正确的值。
I/flutter ( 9290): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 9290): The following RangeError was thrown building SettingsPage(dirty, dependencies: [MediaQuery], state:
I/flutter ( 9290): _SettingsPageState#c0ade):
I/flutter ( 9290): RangeError (index): Invalid value: Valid value range is empty: 0
I/flutter ( 9290): When the exception was thrown, this was the stack:
I/flutter ( 9290): #0 List.[] (dart:core-patch/growable_array.dart:145:60)
I/flutter ( 9290): #1 _SettingsPageState.build (package:my_fitness_tools/pages/settings_page.dart:175:45)
I/flutter ( 9290): #2 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
I/flutter ( 9290): #3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3739:15)
I/flutter ( 9290): #4 Element.rebuild (package:flutter/src/widgets/framework.dart:3565:5)
I/flutter ( 9290): #5 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3722:5)
I/flutter ( 9290): #6 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3864:11)
I/flutter ( 9290): #7 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3717:5)
I/flutter ( 9290): #8 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2961:14)
I/flutter ( 9290): #9 Element.updateChild (package:flutter/src/widgets/framework.dart:2764:12)
I/flutter ( 9290): #10 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4876:14)
I/flutter ( 9290): #11 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2961:14)
I/flutter ( 9290): #12 Element.updateChild (package:flutter/src/widgets/framework.dart:2764:12)
这是我的脚手架。
Scaffold(
appBar: new AppBar(
backgroundColor: Options.selectedTheme.primaryColorDark,
centerTitle: true,
title: Text("Settings"),
),
drawer: DrawerApp(),
body:
new Stack(
children: <Widget>[
new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/backgrounds/Sfondo.jpg"),
fit: BoxFit.fill)),
),
ListView( // vertical listview
children: <Widget>[
//Inizio oggetti in ordine verticale della pagina.
SizedBox(
height: 10.0,
),
titleSettings("Timers"),
Container(
height: MediaQuery.of(context).size.height,
child: ListView( // horizontal Listview
shrinkWrap: true,
physics: ClampingScrollPhysics(),
scrollDirection: Axis.horizontal,
children: <Widget>[
timerColumn(timersList[0], 0), // line 175
timerColumn(timersList[1], 1),
timerColumn(timersList[2], 2),
timerColumn(timersList[3], 3),
timerColumn(timersList[4], 4),
timerColumn(timersList[5], 5),
],
),
),
],
)
编辑列表 timersList = [0,0,0,0,0,0] 修复了该问题。但我有一个问题。如果我现在想在另一个文件中使用这些值。我为加载做了同样的功能。但我得到这个错误。 声明所有内容和功能时也是如此,但为什么它想要静态而不是之前的文件?
解决方案
这几乎肯定与执行顺序有关。您需要在未显示的代码中寻找答案。
- 小部件状态已创建
- [30.0 等分配给
timersValueList
initState
调用,大概是调用...loadSharedPreferences
调用,但暂停等待getInstance
,允许...- 框架调用
build
- 显示当前值 (30) getInstance
完成,所以loadSharedPreferences
继续分配 [35.0, 等等timersValueList
- 在您进行更新之前,不会通知小部件其状态已更改。
setState
在末尾添加一个调用以loadSharedPreferences
通知框架更改。
void loadSharedPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> myList = prefs.getStringList('mylist') ?? ['30', '60', '90'];
List<double> myOriginalList = myList.map((i) => double.parse(i)).toList();
setState(() {
timersValuesList = myOriginalList;
});
}
编辑
我会把你改成State
这样:
class _SettingsPageState extends State<SettingsPage> {
List<double> timersList;
@override
initState() {
super.initState();
loadTimers();
}
saveTimers(List<double> timersList) async {
List<String> convertedTimerValues = timersList.map((i) => '$i').toList();
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setStringList('TimerList', convertedTimerValues);
}
loadTimers() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> myList = prefs.getStringList('TimerList');
setState(() {
timersList = (myList == null)
? [30.0, 60.0, 90.0, 120.0, 150.0, 180.0]
: myList.map((i) => double.parse(i)).toList();
});
}
@override
Widget build(BuildContext context) {
if (timersList == null) return Center(child: CircularProgressIndicator());
return Whatever(/* Fill me in with the normal page*/);
}
}
您需要timersList
在 a中赋值,setState
以便框架知道您已更改状态!这将导致它重建小部件。请注意,在build
您必须应对timersList
为空的情况。它为空表示您仍在等待事情发生,因此应该呈现一个占位符。
推荐阅读
- mysql - 如何计算老化报告的月销售额
- node.js - 如何从NodeJS中的缓冲区流式传输范围http请求
- mysql - 按有收入的订单数量分组的客户数量
- python - 如何根据连续行在 Pandas 中进行透视和聚合,而两列没有变化?
- typescript - Typescript Sum Pluck 类型
- sql - 在 Hive 中聚合 ID-property-value 记录
- python-2.7 - GCP 部署管理器,尝试将角色分配给用户组或服务帐户时出错
- azure - 在 Azure Active Directory 中为自定义应用提供条件访问的多重身份验证
- python - Python BS4 Beautiful Soup HTML.Parser 在网站上不起作用
- image - Xamarin Forms如何水平填充图像视图并垂直扩展?