В предыдущем параграфе мы начали большую тему, посвящённую обзору библиотек для работы с данными разных типов — успели поговорить о файлах. В этом параграфе поговорим про работу с парами ключ — значения.
Простейшие хранилища формата ключ — значение (Key — Value) не являются подвидами каких-либо баз данных (SQL/NoSQL) и представляют собой легковесное и простое решение для специфических задач, таких как кэширование и хранение настроек.
Они не предназначены для обработки больших объёмов данных или сложных операций.
Мы рассмотрим три библиотеки:
-
shared_preferences; -
flutter_secure_storage; -
get_storage.
Библиотека shared_preferences
shared_preferences — это библиотека, позволяющая сохранять примитивные данные в формате ключ — значение (key — value) на устройстве пользователя и доступная на всех платформах, в том числе в вебе. Она предоставляет удобный способ хранения настроек приложения и иных простых данных — сохраняется/читается обыкновенный текстовый файл на iOS в формате .plist (NSUserDefaults) и на Android в формате .xml (SharedPreferences).
Вы уже могли видеть пример пользования данной библиотекой ранее. Сейчас разберём её возможности и методы подробнее.
Использование
Для начала работы с shared_preferences необходимо импортировать соответствующий пакет:
1import 'package:shared_preferences/shared_preferences.dart';
После этого с помощью метода getInstance() вы можете получить инстанс SharedPreferences. Он представляет собой синглтон:
1void main() async {
2 final sharedPrefs = await SharedPreferences.getInstance();
3 // Далее вы можете использовать sharedPrefs для чтения и записи данных
4}
Когда мы достаём инстанс, то все данные выгружаются в оперативную память. Поэтому вы можете синхронно доставать из неё данные — это будет быстрая операция. При этом запись данных — это асинхронная дисковая операция. Таким образом, одновременно происходит запись и в оперативную память, и в файл.
Функции записи возвращают булево значение. Оно сигнализирует, удалась запись или нет. Почти всегда возвращается true, но в теории может вернуться и false, хотя такое маловероятно. Например, это может произойти на iOS, когда интерфейс NSUserDefault записывает в кэш и синхронизируется не сразу. В таких случаях нужно быть готовыми к тому, что данные не запишутся, и сделать соответствующую запись в логах либо попробовать повторить попытку записи.
Вот как выглядит файл с настройками SharedPreferencesв системе Android. Найти его можно по следующему пути: /data/data/<application_ID>/shared_prefs/FlutterSharedPreferences.xml.
1<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
2<map>
3 <string name="flutter.user_nickname">yandex_student</string>
4 <boolean name="flutter.is_night_theme" value="true" />
5 <long name="flutter.age" value="20" />
6</map>
Теперь поговорим о методах инстанса SharedPreferences.
Чтение данных
shared_preferences предоставляет методы для синхронного чтения различных типов данных:
-
get(String key)— синхронное чтение данных по ключу. -
getBool(String key)— синхронное чтение булевых данных по ключу. -
getInt(String key)— синхронное чтение целочисленных данных по ключу. -
getDouble(String key)— синхронное чтение числовых данных с плавающей точкой по ключу. -
getString(String key)— синхронное чтение строковых данных по ключу. -
containsKey(String key)— проверяет наличие ключа. -
getStringList(String key)— синхронное чтение списка строк по ключу.
Пример считывания строки:
1final username = sharedPrefs.getString('username');
Запись данных
Для записи данных в shared_preferences используйте асинхронные методы:
-
setBool(String key, bool value)— асинхронная запись булевых данных по ключу. -
setInt(String key, int value)— асинхронная запись целочисленных данных по ключу. -
setDouble(String key, double value)— асинхронная запись числовых данных с плавающей точкой по ключу. -
setString(String key, String value)— асинхронная запись строковых данных по ключу. -
setStringList(String key, List<String> value)— асинхронная запись списка строк по ключу.
Пример записи строки:
1await sharedPrefs.setString('username', 'john_doe');
Удаление данных
Вы также можете удалить данные, связанные с определённым ключом, с помощью метода remove(String key):
1await sharedPrefs.remove('username');
Где хранится файл с настройками shared_preferences
Это зависит от платформы:
-
Android — данные хранятся в файле XML в папке SharedPreferences.
-
iOS — данные хранятся с использованием класса
NSUserDefault. -
macOS — данные также хранятся с использованием
NSUserDefault. -
Linux — данные хранятся в папке
.configв XDG_DATA_HOME. -
Windows — данные хранятся в Roaming AppData директории.
-
Web — данные хранятся в кэше браузера.
Преимущества и недостатки shared_preferences
Преимущества |
Недостатки |
|
|
Библиотека shared_preferences — это хороший инструмент для хранения простых данных во Flutter. Она предоставляет простой и удобный способ управления настройками приложения и другими данными на стороне клиента. Несмотря на некоторые ограничения, она остаётся одним из популярных выборов для хранения ключевых данных.
Библиотека flutter_secure_storage
flutter_secure_storage — это библиотека для безопасного хранения конфиденциальных данных в приложениях Flutter. Она поддерживает все платформы, что делает её отличным выбором для хранения и управления чувствительными данными.
Основные возможности
-
Поддержка Android и iOS. На Android библиотека использует систему управления ключами Keystore с RSA шифрованием или Android EncryptedSharedPreferences (расширение над SharedPreferences с поддержкой шифрования) в зависимости от настроек. На iOS данные хранятся в Keychain — криптоконтейнере для хранения чувствительной информации, включая ключи, учётные данные, сертификаты.
-
Простой API. Вы можете легко записывать, читать и удалять данные из
flutter_secure_storage. Ниже приведён пример сохранения и чтения значения в защищённом хранилище.
1import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2
3const storage = FlutterSecureStorage();
4await storage.write(key: 'key', value: 'value');
5final value = await storage.read(key: 'key');
6await storage.delete(key: 'key');
Для более продвинутого хранения данных и их обмена между разными приложениями одного разработчика на iOS существует технология App Group, которую также можно конфигурировать для использования с flutter_secure_storage.
AppGroups
AppGroups — это функциональность, специфичная для iOS, которая позволяет приложениям одного разработчика совместно использовать данные. Это особенно полезно, когда несколько ваших приложений нуждаются в доступе к общим данным — например, для авторизации пользователя.
Пример ниже позволяет разделять данные между приложениями группы group.example. Это означает, что другое приложение, настроенное на использование этой же группы, сможет получить доступ к хранимым данным по ключу key.
1import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2
3final storage = FlutterSecureStorage();
4await storage.write(
5 key: 'key',
6 value: 'value',
7 iOptions: IOSOptions(groupId: 'group.example'),
8);
Для использования AppGroups вам необходим аккаунт разработчика и настройка разрешений в консоли разработчика Apple. Подробнее об этом можно почитать в разделе Configuring App Groups на официальном сайте разработчика Apple.
Преимущества и недостатки flutter_secure_storage
Преимущества |
Недостатки |
|
|
Библиотека отлично подходит для приложений, требующих безопасного хранения таких данных, как токены аутентификации, пароли и другие чувствительные данные.
Библиотека get_storage
get_storage — это ещё одна библиотека для Flutter, предназначенная для хранения простых данных в памяти устройства. Она предоставляет простой и интуитивно понятный интерфейс для работы с хранилищем, позволяя сохранять и получать данные без лишних сложностей.
Основные возможности
Простой интерфейс. Библиотека get_storage предоставляет простые методы для записи и чтения данных.
1import 'package:get_storage/get_storage.dart';
2
3...
4
5main() {
6 await GetStorage.init();
7 ...
8}
9
10...
11
12final box = GetStorage();
13box.write('key1', 'value');
14box.write('key2', 3);
15final value = box.read('key1');
Запись и чтение. Этот плагин оптимизирован для быстрого доступа к данным, что делает его подходящим для хранения часто используемых значений.
Поддержка разных типов данных. Вы можете сохранять данные различных типов, таких как строки, числа, булевы значения и объекты, используя динамическую типизацию.
Пример использования
1import 'package:get_storage/get_storage.dart';
2
3final box = GetStorage();
4
5// Записываем значение
6box.write('username', 'JohnDoe');
7
8// Читаем значение
9final username = box.read('username');
10
11// Проверяем наличие ключа
12if (box.hasData('username')) {
13 // Делаем что-то, если ключ существует
14}
Преимущества и недостатки get_storage
Преимущества |
Недостатки |
|
|
get_storage может быть полезен для хранения настроек пользователя, временных данных и другой информации, которая не требует сложных манипуляций с базами данных.
До этого момента мы рассматривали хранение данных в обычных текстовых файлах, что подходит для простых структур данных и для малых объёмов этих самых данных. Когда требования к данным возрастают, следом появляется необходимость в использовании более удобных и надёжных инструментов для работыс данными.
Помочь нам в этом призваны базы данных. О них и поговорим в следующем параграфе.
