Flutter:如何将用户创建的对象存储在本地存储中并将它们检索到 ListView 中

Flutter: How can I store user created objects in local storage and retrieve them into a ListView

我正在 Flutter 中重新创建我的应用程序 Call Manager,但我很难存储对象并将它们检索到列表中。使用 SharedPreferences 和 GSON 适用于完整的 Android 应用程序,但由于 GSON 在 Flutter 中不存在,在我看来,将 onjects 存储为 JSON 数据是可行的方法。

流程应该是这样的: 用户在 AddNewCall 屏幕上添加一个新呼叫。这包括姓名、phone 号码和可选说明' 当用户单击 'Save' 按钮时,将根据这些字段中的文本创建一个 Call 对象。该对象被编码成这样的字符串:String jsonData = json.encode(newCallObject); 使用 getApplicationDocumentsDirectory() 将通话 JSON 数据保存到应用程序的本地存储中 用户被带回主屏幕,其中 JSON 文件将在 initState() 方法中异步加载到应用程序中。 JSON 数据被解码并添加到 ListView 我遇到的问题是,当 JSON 数据添加到文件是第 3 步时,它看起来像这样:{sampleData}{sampleData} 而不是作为数组被包围在 [] 中。因此,应用程序在读取文件时出现问题。到目前为止,我的解决方案是将文件的内容解析为一个数组,在 }{ 之间添加一个下划线,并将结果字符串拆分为一个字符串类型的数组。它看起来像这样:

String jsonCalls = await file.readAsString();
jsonCalls = jsonCalls.replaceAll('}{', '}_{');
List<String> temp = jsonCalls.split('_');

所以现在我得到了一个包含 JSON 字符串的数组,但我仍然无法访问每个 JSON 字符串中的值。我采用的整个方法似乎也过于复杂了。一定有更好的方法,但我疯狂地用谷歌搜索却一无所获。你们能帮帮我吗?

谢谢!

这里有一些建议

  1. Flutter 支持使用 plugin 的共享首选项,因此它应该与 Android 相似。
  2. initState 仅在第一次初始化 StatefulWidget 时调用,因此可能不是期望重新加载更改信息的好地方
  3. 考虑将您的工作状态保存在内存中,例如在 List<Call> 中,您可以轻松地向其中添加新调用。
  4. 当您将此 List 序列化为 json 时,它将按预期包含在括号中。写入整个列表,覆盖之前的版本。
  5. 使用后备存储(文件或共享首选项)作为应用程序使用之间的持久性,因此在启动时读取一次,并在每次修改时将其写入内存中。内存中的副本是主副本,而应用程序是 运行.

这应该可以减少将 json 破解为字符串的需要。

可能是这样的:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Call Manager',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Call> calls = [];

  @override
  void initState() {
    super.initState();
    load();
  }

  load() async {
    // initially populate calls by getting last value from shared preferences and parsing it
  }

  persist() async {
    // encode calls as json and write to share prefs
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Calls'),
      ),
      body: new ListView(
        scrollDirection: Axis.horizontal,
        children: calls
            .map((call) => new ListTile(
                  title: new Text(call.phoneNumber),
                ))
            .toList(),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          Navigator.push<Call>(
            context,
            new MaterialPageRoute(
              builder: (context) => new SecondPage(),
            ),
          ).then((newCall) {
            if (newCall != null) {
              setState(() {
                calls.add(newCall);
              });
              persist();
            }
          });
        },
        tooltip: 'New',
        child: new Icon(Icons.add),
      ),
    );
  }
}