【问题标题】:flutter sharedpreferences not setting state from first built颤振 sharedpreferences 未从第一次构建时设置状态
【发布时间】:2019-05-21 02:47:13
【问题描述】:

我正在尝试在加载应用程序时加载 sharedPreferences 中保存的值。但它总是给我在第一次构建时双重声明的静态列表 [0,0,0,0,0,0]。每当我触摸设置状态的东西时,它都会更改为我的正确值。我什至不需要那个静态列表,我只是声明它,因为 dart 在问我。如果那里没有保存任何内容,我想要默认列表,否则我想要 sharedpreferences 保存列表。这是我的代码。

@override initState()  {
    super.initState();
    callLoad();
  }

  callLoad() async{
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
    });
  }

  Future<List<double>> loadTimers() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
      if (myList == null ){
        return defaultTimersList;
      } else{
        savedTimerList = myList.map((i)=> double.parse(i)).toList();
        return savedTimerList;
      }
  }

  static List<double> timersList = [0,0,0,0,0,0];

  double timeRemaining1 = timersList[0];
  double timeRemaining2 = timersList[1];
  double timeRemaining3 = timersList[2];
  double timeRemaining4 = timersList[3];
  double timeRemaining5 = timersList[4];
  double timeRemaining6 = timersList[5];

我也试过这种方法,但它是一样的。

@override initState()  {
    super.initState();
    loadTimers();
  }


  loadTimers() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
      if (myList == null ){
        setState(() {
          timersList = defaultTimersList;

        });
      } else{
        savedTimerList = myList.map((i)=> double.parse(i)).toList();
         setState(() {
           timersList = savedTimerList;
         });
      }
  }

  static List<double> timersList = [0,0,0,0,0,0];

  double timeRemaining1 = timersList[0];
  double timeRemaining2 = timersList[1];
  double timeRemaining3 = timersList[2];
  double timeRemaining4 = timersList[3];
  double timeRemaining5 = timersList[4];
  double timeRemaining6 = timersList[5];

谢谢

使用显示问题的小应用进行编辑。

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 chokuns 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;

  @override initState()  {
    super.initState();
    callLoad();
  }

  callLoad() async{
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
    });
  }

  Future<List<double>> loadTimers() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
    if (myList == null ){
      return defaultTimersList;
    } else{
      savedTimerList = myList.map((i)=> double.parse(i)).toList();
      return savedTimerList;
    }
  }

  static List<double> timersList = [0,0,0,0,0,0];

  double timeRemaining1 = timersList[0];
  double timeRemaining2 = timersList[1];
  double timeRemaining3 = timersList[2];
  double timeRemaining4 = timersList[3];
  double timeRemaining5 = timersList[4];
  double timeRemaining6 = timersList[5];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button \nthis many times:',
              textAlign: TextAlign.center,
            ),
            Text(
              '$timeRemaining1', //showing here $timersList it shows correct values
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

  • 就我而言,它运作良好。构建部分如何?
  • 是的,它可以工作,但第一次构建它使用静态列表 timersList 中声明的值,而不是sharedpreferences 中的值。我认为它首先绘制屏幕,​​然后设置值,因为在它启动后任何类型的 setstate 都会正确更新。
  • 我编辑了这个问题。现在你可以用这个小例子更好地检查它。谢谢。

标签: dart flutter


【解决方案1】:

callLoad 更改为:

  callLoad() async{
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
      timeRemaining1 = timersList[0];
      timeRemaining2 = timersList[1];
      timeRemaining3 = timersList[2];
      timeRemaining4 = timersList[3];
      timeRemaining5 = timersList[4];
      timeRemaining6 = timersList[5];
    });
  }

【讨论】:

  • 是的,显然我也可以从 initState 初始化它们调用函数。我觉得很笨。非常感谢理查德的所有帮助。我明白了很多事情,但试图解决这个问题。
  • 我认为 OP 想知道原因。这是一个问题。
  • 嗯,实际上,不,你不能在initState 中这样做,因为未来还没有完成。您通过定义 6 个局部变量所做的就是在 MyHomePageState 中创建一个完整的负载更多状态。问题是您的 callLoad 函数只更新了该状态的一部分 (timersList),但忽略了更新状态的其余部分 (timeRemaining*)。正如@yahocho 指出的那样,这六个变量重复了您已经存储在列表中的内容,但是从您之前的问题中可以明显看出,您出于某种原因需要/想要这些。这就是为什么我离开他们并展示出了什么问题。
【解决方案2】:

基本上,Dart 是通过对象的引用传递的。 所以,你的想法是正确的。但是,我将解释为什么它不起作用。 它是由List&lt;double&gt; list = await loadTimers(); 引起的,因为它是新对象。 下面的代码显示TrueTrue。 但是,如果将//isSameList = identical(timersList, timersList2); 更改为isSameList = identical(timersList, timersList2);,则会显示FalseTrue。您必须重新启动它。

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  SharedPreferences prefs;
  static List<double> timersList = [0,0,0,0,0,0];
  double timeRemaining1;
  List<double> timersList2;
  bool isSameList;
  bool isSameValue;

  @override initState()  {
    super.initState();
    initValues();
    callLoad();
  }

  void initValues()
  {
    timeRemaining1 = timersList[0];
    timersList2 = timersList;
    isSameList = identical(timersList, timersList2);
    isSameValue = identical(timersList[0], timeRemaining1);
  }

  Future<void> callLoad() async{
    prefs = await SharedPreferences.getInstance();
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
      //isSameList = identical(timersList, timersList2);
    });
  }

  List<double> loadTimers() {
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
    if (myList == null ){
      return defaultTimersList;
    } else{
      savedTimerList = myList.map((i)=> double.parse(i)).toList();
      return savedTimerList;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button \nthis many times:',
              textAlign: TextAlign.center,
            ),
            Text(
              '$isSameList'+'$isSameValue', //showing here $timersList it shows correct values
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }

最后,我知道如何使用pass by reference 来作为列表了。

timersList.setAll(0, list);

它很好地显示了结果。但是,timeRemaining1 仍然无法显示,因为它无法保留reference。所以,我认为你可以像上面那样用 List 对象来处理它。

【讨论】:

  • 即使您关闭然后重新启动应用程序,它是否也会显示 sharedPreferences 值?对我来说,它显示所有零,只有在我触摸某些东西后它才会呈现所有正确的值。我也想从第一次构建中获得这些值。
  • 您应该尝试在小部件中显示文本而不是 timersList 而是其索引: timersList[0]
  • 我编辑了我的问题,修改了您的代码,仅在该小部件中使用了剩余定时器值 1 的值,它为我加载了 0.0。请检查一下。谢谢
  • @FlorisMarpepa 我更新了答案。你说的对。我刚刚发现它是由新实例引起的。
猜你喜欢
  • 2019-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 2020-03-14
相关资源
最近更新 更多