Flutter: Как я могу хранить созданные пользователем объекты в локальном хранилище и извлекать их в ListView - PullRequest
0 голосов
/ 05 июня 2018

Я воссоздаю свое приложение Диспетчер вызовов во Флаттере, и мне очень трудно хранить объекты и извлекать их в список.Использование SharedPreferences и GSON хорошо работает для полного Android-приложения, но, поскольку GSON не существует во Flutter, мне кажется, что хранение объектов в виде данных JSON - это путь.

Процесс должен быть следующим: Пользователь добавляет новый вызов на экране AddNewCall.Это включает в себя имя, номер телефона и необязательное описание. «Когда пользователь нажимает кнопку« Сохранить », из этого поля создается текст« Вызов ».Объект закодирован в строку следующим образом: String jsonData = json.encode(newCallObject); Данные вызова JSON сохраняются в локальном хранилище приложения с помощью getApplicationDocumentsDirectory(). Пользователь возвращается на главный экран, где файл JSON будет загружаться в приложение асинхронно вметод initState().Данные JSON декодируются и добавляются в ListView. Проблема, с которой я сталкиваюсь, заключается в том, что, поскольку данные JSON добавляются в файл, это Шаг 3, он будет выглядеть следующим образом: {sampleData}{sampleData} вместо того, чтобы заключаться в [], какмассив.Приложение икнет при чтении в файле из-за этого.Мое решение до сих пор заключалось в том, чтобы разобрать содержимое файла в массив, вставить символ подчеркивания между} {и разбить полученную строку на массив типа String.Это выглядит так:

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

Итак, теперь я получаю массив со строками JSON в них, но я застрял в возможности доступа к значениям в каждой строке JSON.Весь этот подход, который я использую, кажется слишком сложным.Должен быть способ получше, но я погуглил как сумасшедший и ничего не нашел.Ребята, вы в состоянии мне помочь?

Спасибо!

1 Ответ

0 голосов
/ 05 июня 2018

Вот несколько предложений

  1. Flutter поддерживает общие настройки с помощью плагина , поэтому он должен казаться знакомым по 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),
      ),
    );
  }
}
...