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

时间:2018-06-05 00:28:27

标签: json object local-storage storage flutter

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

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

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

所以现在我得到一个包含JSON字符串的数组,但我仍然无法访问每个JSON字符串中的值。我采取的整个方法似乎过于复杂。必须有一个更好的方法,但我已经谷歌搜索疯狂,没有发现任何东西。你们能帮帮我吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

以下是一些建议

  1. Flutter使用plugin支持共享偏好设置,因此Android会感觉很熟悉。
  2. initState仅在StatefulWidget第一次初始化时调用,因此可能不是期望重新加载更改信息的好地方
  3. 考虑将您的工作状态保留在内存中,例如在List<Call>中,您可以随时添加新的呼叫。
  4. 当您将此List序列化为json时,它将按预期包含在括号中。写下整个列表,覆盖以前的版本。
  5. 使用后备存储(文件或共享首选项)作为应用程序使用之间的持久性,因此在启动时读取一次,并在每次在内存中修改时写入。应用程序运行时,内存中的副本是主副本。
  6. 这可以减少将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),
          ),
        );
      }
    }