Самый простой способ записать значения в локальное хранилище.

TL;DR: А вот и pub.dev!

Около года назад я написал эту статью о различных способах записи значений в локальное хранилище. Даже год спустя это одна из моих самых активных статей. Непропорционально большое количество моих просмотров относится к этой статье.

Это означает, что разработчики Flutter пытаются найти лучший способ хранения своих файлов, но после работы над многими проектами стало ясно, что большинство разработчиков не хотят записывать какие-либо файлы в локальное хранилище — по сути, они сериализуют объекты для последующего использования. Такие вещи, как текущие пользователи, данные о счете, кешированные вызовы API… Эти объекты хранятся одинаково каждый раз:

  1. напишите метод toJson и fromJson.
  2. определите, в каком локальном хранилище вы собираетесь хранить объект (общие настройки? каталог документов приложения? каталог поддержки приложений? временный?)
  3. написать метод, который записывает значение в локальное хранилище после сериализации
  4. напишите метод, который считывает это значение и десериализует его в объект
  5. опционально напишите метод удаления

Если вы добрались до шага 6, поздравляем! Теперь сделайте это снова для следующего объекта :).

Другая основная проблема заключается в том, что path_provider не работает в сети, поэтому, если вы переносите свои методы в сеть, вам придется написать kIsWeb чек. Если вы не пойдете по этому пути и не воспользуетесь общим методом, вы в конечном итоге столкнетесь с проблемой безопасности типов: вы должны гарантировать, что то, что вы пишете, это именно то, что вы читаете, иначе ваши преобразования json будут сброшены.

Все это для того, чтобы просто записать в локальное хранилище! Часто повторяющаяся работа должна быть абстрагирована в пакет.

Бывают случаи, когда вам нужно записать на диск сильно структурированные данные. Все в масштабе или все, что должно быть хорошо структурировано или реляционно. Это не для этого — я бы рекомендовал посмотреть на moor, который действительно хорошо справляется с ролью локальной базы данных для Flutter.

Вместо этого local_value предназначен для объектно-ориентированных данных. Лично я уже использовал свой собственный пакет (тестовая версия!) в двух приложениях.

  • Чтобы записать токены доступа на диск: я хочу, чтобы они сохранялись с течением времени, но я не так беспокоюсь об их утечке, как в случае с моими токенами обновления.
  • Чтобы написать дерево уведомлений: уведомления во флаттере требуют много управления. Вы должны следить за тем, какое уведомление истекает, какие уведомления приходят и куда они уходят, отслеживать их метаданные и т. д. Я пишу дерево JSON, которое позволяет мне вкладывать данные уведомлений так глубоко, как я хочу.
  • Чтобы написать текущего пользователя: Текущий пользователь имеет некоторые данные, такие как имя и идентификатор. Это обязательно хранится на бэкэнде, но извлекать его каждый раз — большая проблема и пустая трата времени. Вместо этого я записываю его на диск, используя local_singleton .
  • Для ведения списка: у меня есть приложение, которое служит моделью федеративного обучения для химического анализа на основе цвета (на самом деле я ничего не знаю о химии, я работаю на химическом факультете моей школы!). Пользователь может извлекать модели из облака. Я не хочу, чтобы пользователю приходилось каждый раз заново извлекать данные, поэтому я сохраняю их на диск с помощью LocalValue!

Я не буду вдаваться в подробности о том, как использовать, но вот фрагмент из readme:

//locally save a singleton:
final localCounterValue = LocalSingleton<int>(id: 'counter_val');
await localCounterValue.write(5);
print(await localCounterValue.read()); //5
//or save multiple related objects:
final localUserScores = LocalValue<int>(basePath: ['user_scores']);
await localUserScores.write('user_1', 15);
await localUserScores.write('user_2', 24);
print(await localUserScores.read('user_1')); //prints 15
print(await localUserScores.read('user_2')); //prints 24

Думаю, очень простой API с большой гибкостью.

Но не верь мне на слово: иди и попробуй сам!

Если у вас есть предложения / проблемы, пожалуйста, дайте мне знать, и я всегда открыт для обучения. Если вы столкнулись с ошибкой или хотите предложить функцию, перейдите к проблемам github, чтобы сообщить мне!

Я не получаю от этого абсолютно никакой финансовой выгоды и никогда не собираюсь. Я просто хотел написать это, чтобы помочь людям.