草庐IT

dart - 保存和加载,共享首选项

coder 2023-07-23 原文

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,所以我认为该值已保存但在首次启动时未正确显示。之后添加值可以正常工作。有人能帮我吗?我找不到办法做到这一点。也许我应该在保存功能中放入默认值,以防不存在任何已保存的文件?感谢帮助保存和加载双列表的代码,因为我认为我做得不好。再次感谢。

这是我做的。 (我可以在 initState 中调用任何异步函数,所以我调用了一个外部函数)。但我得到错误:“NoSuchMethodError:方法“[]”被调用为空。 接收者:空 尝试调用:“

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] 解决了这个问题。 但我有一个问题。如果我现在想在另一个文件中使用这些值。我已经为加载做了完全相同的功能。但是我得到了这个错误。 声明所有内容和功能也是一样,但为什么它想要静态而不是之前的文件?

最佳答案

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

  1. 已创建小部件状态
  2. [30.0 等分配给 timersValueList
  3. initState 调用了,大概调用了...
  4. loadSharedPreferences 已调用,但暂停等待 getInstance,允许...
  5. 框架调用 build - 显示当前值 (30)
  6. getInstance 完成,因此 loadSharedPreferences 继续将 [35.0 等分配给 timersValueList
  7. 在您进行更新之前,不会通知小部件其状态已更改。

loadSharedPreferences 末尾添加对 setState 的调用,以通知框架更改。

  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*/);
  }
}

您需要在 setState 中分配给 timersList,以便框架知道您已经更改了状态!这将导致它重建小部件。请注意,在 build 中,您必须应对 timersList 为 null 的情况。它为 null 表示您仍在等待事情发生,因此应该呈现一个占位符。

关于dart - 保存和加载,共享首选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56159374/

有关dart - 保存和加载,共享首选项的更多相关文章

  1. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  2. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  5. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  6. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  7. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  8. ruby - Watir 更改 Mozilla Firefox 首选项 - 2

    我正在使用Watir运行一个Ruby脚本来为我自动化一些事情。我试图自动将一些文件保存到某个目录。因此,在我的Mozilla设置中,我将默认下载目录设置为桌面并选择自动保存文件。但是,当我开始运行我的脚本时,这些更改并没有反射(reflect)出来。似乎首选项恢复为默认值。我已经包括以下内容require"rubygems"#Optional.require"watir-webdriver"#Forwebautomation.require"win32ole"#Forfilesavedialog.并打开一个新的firefox实例:browser=Watir::Browser.new(:

  9. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

  10. ruby - 在模块/类之间共享全局记录器 - 2

    在许多ruby​​类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..

随机推荐