保存和加载,共享首选项

时间:2019-05-16 00:45:10

标签: dart flutter

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个double值的列表,这些值在其他小部件中使用并且可以修改。现在的问题是,每次我打开应用程序时,它都不会使我看到更新和修改后的值,而是总是我声明为默认值的第一个。例如。我编辑了第一个值,它变成了这样。

timersValuesList[0] = 35

然后我将其保存并退出应用。当我重新启动该应用程序时,它显示的值为30而不是应有的35。但是,例如,如果我使用+1进行编辑,则它会直接跳到36,所以让我觉得值已保存但在首次启动时未正确显示。之后,添加值将正常工作。有人能帮我吗?我找不到解决办法。也许我应该在保存功能中添加默认值,以防万一不存在任何已保存的文件?非常感谢您提供有关保存和加载double列表的代码的帮助,因为我认为我做得不好。再次感谢。

我做了这个。 (我可以在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]修复了该问题。 但是我有一个问题。如果我现在想在另一个文件中使用这些值。我已经完成了相同的加载功能。但是我得到这个错误。 enter image description here 在声明所有内容和功能时都一样,但是为什么它要是静态的而不是以前的文件呢?

1 个答案:

答案 0 :(得分:1)

几乎可以肯定这与执行顺序有关。您需要在未显示的代码中寻找答案。

  1. 小工具状态已创建
  2. [30.0,以此类推,分配给timersValueList
  3. initState被呼叫,大概会呼叫...
  4. loadSharedPreferences已调用,但暂停等待getInstance,允许...
  5. 框架调用build-显示当前值(30)
  6. getInstance完成,因此loadSharedPreferences继续将[35.0等分配给timersValueList
  7. 在进行更新之前,没有任何东西会通知微件其状态已更改。

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内分配给setState,以便框架知道您已更改状态!这将导致它重建小部件。请注意,在build中,您必须应对timersList为空。为空表示您仍在等待事情发生,因此应渲染一个占位符。