Sharedpreferences android что это
SharedPreferences
Чтобы получить экземпляр класса SharedPreferences для получения доступа к настройкам в коде приложения используются три метода:
Все эти методы возвращают экземпляр класса SharedPreferences, из которого можно получить соответствующую настройку с помощью ряда методов:
Обратите внимание, что тип double не поддерживается.
Чтобы создать или изменить Общие настройки, нужно вызвать метод getSharedPreferences в контексте приложения, передав имя общих настроек (имя файла):
Для любознательных могу добавить, что файлы настроек хранятся в каталоге /data/data/имя_пакета/shared_prefs/имя_файла_настроек.xml. Поэтому в отладочных целях, если вам нужно сбросить настройки в эмуляторе, то при помощи перспективы DDMS, используя файловый менеджер, зайдите в нужную папку, удалите файл настроек и перезапустите эмулятор, так как эмулятор хранит данные в памяти, которые он сбрасывает в файл. На устройстве вы можете удалить программу и поставить ее заново, то же самое можно сделать и на эмуляторе, что бывает проще, чем удалять файл настроек вручную и перезапускать эмулятор.
Если открыть файл настроек текстовым редактором, то можно увидеть приблизительно такое:
В данном случае в настройках хранятся только строковые значения.
Сохранение значений параметров
Для удобства создадим константу для имени файла настроек, например:
Далее нужно создать параметры, которые вы хотите сохранять в настройках. Удобнее их сделать константами:
Когда вы определили названия параметров, то можете сохранять любые значения этих параметров. Для этого создаём переменную, представляющую экземпляр класса SharedPreferences:
Внутри метода onCreate() вы инициализируете эту переменную:
Вы передаёте в указанный метод название вашего файла (он будет создан автоматически) и стандартное разрешение, дающее доступ только компонентам приложения.
Чтобы внести изменения в настройки (редактировать), нужно использовать класс SharedPreferences.Editor. Получить объект Editor можно через вызов метода edit объекта SharedPreferences, который вы хотите изменить. После того, как вы внесли все необходимые изменения, вызовите метод commit() или apply() объекта Editor, чтобы изменения вступили в силу. Метод apply() появился в API 9 и работает в асинхронном режиме, что является более предпочтительным вариантом. Метод commit() приходится использовать для старых версий и кроме того, он возвращает значение true в успешном случае и false в случае ошибки. Если вам надо отслеживать ошибки, то используйте его.
Предположим, что у нас есть два текстовых поля, где пользователь должен ввести имя кота и его и возраст. Чтобы сохранить параметр, нужно получить текст, который ввел пользователь, через метод getText().toString():
Получив нужный текст, сохраняем его через метод putString() (есть также putLong(), putBoolean() и т.п.):
Как правило, параметры сохраняют в методах активности onPause() или onStop() в тех случаях, когда данные требуются сохранить между запусками приложения. Но могут быть и другие сценарии.
Чтение значений параметров
Для считывания данных при загрузке приложения обычно используют методы onCreate() или onResume(). Нам нужно получить доступ к настройкам программы и проверить, есть ли среди них нужный нам параметр. Нас интересует ключ Nickname. Если мы его найдём, то загрузим его значение в текстовое поле.
В этих строчках кода мы проверили существование параметра APP_PREFERENCES_NAME и получили его значение через getString(), передавая ключ и значение по умолчанию (используется в том случае, если для данного ключа пока что не сохранено никакое значение). Осталось только загрузить полученный результат в текстовое поле.
Аналогично поступаем и с другими параметрами через методы get () (getLong, getBoolean() и т.д.).
Если вам ещё не понятно, то ниже исходный код:
Показать код (щелкните мышкой)
Можно получить ассоциативный массив со всеми ключами и значениями через метод getAll(). После этого можно проверить наличие конкретного ключа с помощью метода contains().
Очистка значений
Для очистки значений используйте методы SharedPreferences.Editor.remove(String key) и SharedPreferences.Editor.clear().
Методы getStringSet() и putStringSet()
Начиная с API 11, у класса SharedPreferences появился новый метод getStringSet(), а у класса SharedPreferences.Editor родственный ему метод putStringSet(). Данные методы позволяют работать с наборами строк, что бывает удобно при большом количестве настроек, которые нужно сразу записать или считать.
Удаление файла
Как я уже сказал, файл настроек хранится в /data/data/имя_пакета/shared_prefs/имя_файла_настроек.xml. Вы можете удалить его программно, например так:
Учтите, что данные могут оставаться в памяти и временном файле *.bak. Поэтому, даже после удаления файла, он может заново воссоздаться. Вообще удалять файл не рекомендуется. Он автоматически удалится при удалении самой программы.
Если вы хотите сохранить информацию, которая принадлежит активности и не должна быть доступна другим компонентам (например, переменным экземпляра класса), вы можете вызвать метод Activity.getPreferences() без указания названия Общих настроек. Доступ к возвращённому ассоциативному массиву Общих настроек ограничен активностью, из которой он был вызван. Каждая активность поддерживает только один безымянный объект Общих настроек.
Сохранение настроек на SD-карту
Сам файл с настройками хранится в системе и обычному пользователю он не виден. Если вам понадобится получить все значения, хранимые в настройках, то вы можете считать все данные при помощи метода getAll() и записать их в файл, который можно сохранить на SD-карте:
Я у тебя первый?
Предположим, вы хотите выводить пользователю какую-то информацию при первом запуске приложения (краткую инструкцию, заставку и т.п.).
Запомнить пользователя
Иногда требуется запомнить имя пользователя или другие данные (пин-код, номер телефона и т.д.). В этом случае вам также подойдут предпочтения, когда вы просто сохраняете нужную строку из текстового поля:
Запомнить состояние переключателей
Если нужно запомнить состояние переключателей, то код может быть таким. Создадим разметку с тремя переключателями.
Код, который отслеживает выбор переключателя и записывает состояние в настройки.
getDefaultSharedPreferences()
В используемых примерах я использовал getSharedPreferences() с придумыванием имени файла для хранения настроек. Этот способ придаёт гибкости в том случае, когда вам нужно создать несколько отдельных файлов. Но если вам нужен один файл, то можно ничего не придумывать, а использовать метод getDefaultSharedPreferences() из объекта PreferencesManager. Система сама сгенерирует имя файла из имени вашего пакета с добавлением слова _preferences. Вот как выглядит связка из трёх методов в исходниках Android (обратите внимание на выделенный текст).
Поэтому примеры можно переделать следующим образом.
Удаляем файл настроек
В API 24 появился новый метод, позволяющий удалить сам файл настроек. До этого можно было удалить своими силами, зная его местоположение. Поэтому универсальный код будет приблизительно следующим.
Gamedev suffering
Блог о разработке игр и серверных технологиях
Android: использование SharedPreferences для сохранения настроек
Для большинства приложений требуется сохранить настройки, управляющие поведением программы. Android предоставляет несколько альтернативных способов сохранения данных приложения, каждый из которых оптимизирован для определенных нужд.
Общие настройки — простой и легкий механизм, основанный на парах «ключ — значение» и предназначенный для сохранения примитивных данных приложения, чаще всего пользовательских настроек.
Введение
Класс SharedPreferences позволяет создавать в приложении именованные ассоциативные массивы типа «ключ — значение», которые могут быть использованы различными компонентами приложения (работая при этом в контексте одного и того же приложения).
Общие настройки поддерживают базовые типы boolean, string, float, long и integer, что делает их идеальным средством для быстрого сохранения значений по умолчанию, переменных экземпляра класса, текущего состояния UI и пользовательских настроек.
Создание и сохранение настроек
Чтобы создать или изменить Общие настройки, нужно вызвать метод getSharedPreferences в контексте приложения, передавая имя общих настроек, которые вы хотите изменить. Настройки недоступны для других приложений.
Получение общих настроек
Очистка/удаление значения
Файл настроек хранится в /data/data/package_name/shared_prefs/имя_файла_настроек.xml. Можно удалить:
Preferences Framework
В примерах выше происходило обычное сохранение и восстанавлениеи нужных параметров. То есть, создаётся свой xml-файл разметки и размещаются там нужные элементы управления. Но Android для этих целей предоставляет собственный Preferences Framework, с помощью которого можно создавать индивидуальный набор предпочтений и встраивать их в приложения.
Определение параметров в string.xml и array.xml
Естественно, необходимо определить все переменные. В string.xml:
А так же в array.xml:
PreferenceActivity
Метод addPreferencesFromResource() считывает установленные настройки из XML-файла, где хранятся наши ресурсы, и делает их доступными для программы. В результате мы должны увидеть настройки на экране. Если автоматически наше Activity не было зарегестрировано, то добавим в манифесте AndroidManifest.xml:
Ну и напишем код, чтобы при клике на меню, открывалось наше окно с настройками. Для этого определим метод по созданию меню и onCreateOptionsMenu и метод, отслеживающий нажатия по меню onOptionsItemSelected :
Теперь при вызове меню опций, нажимайте на пункт «Настройки» и откроется наше окно настроек.
Для сохранения предпочтений на выбор есть 4 класса:
Конкретно в данном примере используется EditTextPreference и ListPreference.
Так выглядит окно изменения для настроек:
Отслеживание изменений в общих настройках
Класс onSharedPreferenceChangeListener позволяет вызвать callback-метод в момент добавления, удаления или изменения конкретной Общей настройки. Используя этот обработчик, компоненты вашего приложения могут следить за изменениями в настройках, установленных пользователем, и обновлять пользовательский интерфейс или корректировать поведение программы.
This function is not relevant for a modern fragment-based PreferenceActivity
This function is not relevant for a modern fragment-based PreferenceActivity. Inflates the given XML resource and adds the preference hierarchy to the current preference hierarchy.
С версии 3.0 появились так называемые Fragments, с помощью которых можно работать с настройками.
Ещё раз повторю, если у вас старый вариант для работы с настройками используется, то он будет работать на всех устройствах нормально. Но если вы пишите для устройств с версией Android 3+, то лучше используйте фрагменты.
Полный список
— хранение данных с помощью Preferences
Хватит об Intent и Activity. Поговорим о хранении данных. В Android есть несколько способов хранения данных:
Мы начнем с самого простого – Preferences. Значения сохраняются в виде пары: имя, значение. Так же, как и например extras в Intent.
Разработаем приложение. В нем будет поле для ввода текста и две кнопки – Save и Load. По нажатию на Save мы будем сохранять значение из поля, по нажатию на Load – загружать.
Project name: P0331_SharedPreferences
Build Target: Android 2.3.3
Application name: SharedPreferences
Package name: ru.startandroid.develop.p0331sharedpreferences
Create Activity: MainActivity
Откроем main.xml и создадим такой экран:
Поле ввода и две кнопки.
Теперь пишем код в MainActivity.java:
Определение элементов экрана, присвоение обработчиков и реализация onClick – тут все понятно и как обычно. Нам интересны методы, которые мы вызываем в onClick
saveText – сохранение данных. Сначала с помощью метода getPreferences получаем объект sPref класса SharedPreferences, который позволяет работать с данными (читать и писать). Константа MODE_PRIVATE используется для настройки доступа и означает, что после сохранения, данные будут видны только этому приложению. Далее, чтобы редактировать данные, необходим объект Editor – получаем его из sPref. В метод putString указываем наименование переменной – это константа SAVED_TEXT, и значение – содержимое поля etText. Чтобы данные сохранились, необходимо выполнить commit. И для наглядности выводим сообщение, что данные сохранены.
Все сохраняем, запускаем приложение.
Для начала, давайте убедимся, что сохранение в принципе нужно. Введите какой-нить текст в поле ввода
и не нажимая кнопку Save закройте приложение кнопкой Назад.
Теперь найдите приложение в общем списке приложений эмулятора
Поле ввода пустое. То, что мы вводили – пропало при закрытии программы. Нажатие на Load тоже ничего не даст – мы ничего не сохраняли.
Давайте попробуем сохранять. Снова введите значение и нажмите Save.
Значение сохранилось в системе.
Теперь закроем приложение (Назад), снова откроем и нажмем Load. Значение считалось и отобразилось.
Давайте сделаем так, чтобы сохранение и загрузка происходили автоматически при закрытии и открытии приложения и не надо было жать кнопки. Для этого метод loadText будем вызывать в onCreate.
(Добавляете только строку 8)
Все сохраним, запустим. Теперь можно вводить данные, закрывать приложение, снова открывать и данные не потеряются. Кнопки Save и Load также работают. В какой момент сохранять данные в ваших приложениях – решать только вам. По нажатию кнопки, при закрытии программы или еще по какому-либо событию. Главное – теперь вы это умеете.
Еще немного слов по этой теме.
Обратите внимание, что в пути к файлу используется наш package.
Теперь разберемся, откуда взялось наименование файла MainActivity.xml. Кроме метода getPreferences, который мы использовали, есть метод getSharedPreferences. Он выполняет абсолютно те же функции, но позволяет указать имя файла для хранения данных. Т.е., например, если бы мы в saveText использовали для получение SharedPreferences такой код:
То данные сохранились бы в файле MyPref.xml, а не в MainActivity.xml.
Теперь если мы посмотрим исходники метода getPreferences, то видим следующее:
Используется метод getSharedPreferences, а в качестве имени файла берется имя класса текущего Activity. Отсюда и появилось имя файла MainActivity.xml.
— используете getPreferences, если работаете с данными для текущего Activity и не хотите выдумывать имя файла.
Кстати, в File Explorer вы можете видеть юниксовые rwx-права доступа к файлу. Попробуйте при сохранении данных использовать не MODE_PRIVATE, а MODE_WORLD_READABLE или MODE_WORLD_WRITEABLE и посмотрите, как будут меняться права.
Полный код MainActivity.java:
На следующем уроке:
— хранение данных с помощью SQLite
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
База данных на SharedPreferences — Android Kotlin
Статья написана об учебном проекте, повторять такое на проде нельзя, как минимум это небезопасно. Намеренно используется не самая лучшая реализация тех или иных вещей, чтобы можно было подискутировать в комментариях.
Зачем всё это? Зачем?
Наверное, в вашей голове возник вопрос: «В каких ситуациях может понадобиться использование SharedPreferences, если абсолютно всё можно хранить в Базе Данных?»
Отвечаю: и правда, абсолютно всю информацию можно хранить в таком виде. Иметь таблицу с настройками приложения (например, тёмная тема: вкл/выкл), а в другой таблице хранить ту самую информацию, которую отображает само приложение. Но эффективно ли это? Если информации много и SQL запросы помогают вам, то да, но не стоит забывать, что Базы Данных в большинстве случаев являются сложным механизмом, из-за чего производительность вашего приложения может быть снижена. Если информации не так много, то гораздо выгоднее использовать SharedPreferences.
Краткая теория, как использовать SharedPreferences
Чтобы получить экземпляр класса SharedPreferences, в коде приложения используются два метода:
Начинаем эксперимент
Представим такой проект: на вход поступает json файл, в нём хранится информация о валютах (имя, стоимость и т. д.). Нам необходимо сохранить эти данные и при перезапуске приложения показать их, не читая json (все данные взяты из нашей БД). Возможные взаимодействия с карточкой валюты: изменение любого поля.
Все исходники вы сможете найти на GitHub в конце статьи.
Создадим самый обыкновенный класс и передадим ему в аргументы context для SharedPreferences. (Хотел бы услышать ваше мнение по поводу классов. Какой класс вы бы предпочли использовать в данной ситуации?)
Мы создадим два пространства. Первое будет хранить информацию о нашей DB и будет статично по своей размерности. В нём будет храниться количество наших карточек с валютами. Второе поле должно хранить те самые карточки, а значит — уметь динамически изменять свой размер.
Как оно будет работать? SharedPreferences хранит данные, как, грубо говоря, Map (ключ->значение), и вся информация находится в «таблице данных». Благодаря имени данной таблицы мы и будем передвигаться по карточкам. Новое имя таблицы = новая карточка. Таблицы мы будем называть цифрами, они будут выполнять роль их id. Так будет намного проще передвигаться по ним.
Создадим и проинициализируем глобальные переменные класса:
А вот и первая наша функция. Она позволяет узнать размер 2 поля (сколько таблиц оно содержит):
Если поле не создано, то возвращается 0.
Геттер создали, теперь время сеттера. Для этого создадим две функции:
Вторая область
Теперь перейдём ко 2 области, нам необходимо уметь перемещаться по нашим «таблицам», для этого реализуем такую функцию:
Стоит немножко объяснить код. В аргументах мы принимаем название таблицы (её порядковый номер), после чего можно заметить проверку, которая сравнивает текущий порядковый номер таблицы с полученным, в случае если они не равны, происходит переприсвоение текущего названия таблицы и её открытие. Доступ к чтению таблицы мы получаем благодаря глобальной переменной prefs, а к редактированию — editor.
Добавление карточек к БД
Что же, думаю, можно перейти к заполнению нашей таблицы:
На вход мы получаем JSON объект, после чего увеличиваем количество всех наших таблиц, открываем новую таблицу и используем сеттеры. Ниже представлен код одного из таких сеттеров:
Подобные сеттеры нужно создать для каждого ключа JSON объекта.
Чтение карточки
Сеттеры отдельных ключей есть, а это значит, что наша самодельная БД уже умеет сохранять информацию, осталось научить её считывать. Ниже приведён пример одного из геттеров:
Мы можем наблюдать, как функция может принимать пользовательское имя таблицы, так и использовать значение по умолчанию. Если пользователь не вводил имя таблицы, то информация будет взята из текущей.
Поиск карточки
Замечательно, наша БД на SharedPreferences умеет сохранять и выводить данные, правда осталась одна нерешённая проблема. Предположим, что при работе с приложением пользователь захочет изменить определённую карточку, нажав на неё, для этого у нас уже существуют сеттеры, но откуда нам знать, какую именно таблицу нужно открыть для работы? Предположим, у нас есть возможность получить какую-нибудь информацию с карточки, например, сокращённое имя валюты. Получается, нам необходимо пройтись по всем существующим таблицам, найти совпадение и вывести название данной таблицы. Это долгая операция, поэтому таких ситуаций лучше не создавать, например, пусть каждая карточка в интерфейсе будет хранить свой локальный номер, который будет совпадать с названием таблицы, но если такой возможности нет, то в бой идёт наша новая «тяжёлая» функция:
В случае если совпадений не найдено, будет возвращено null. Поскольку данная функция, скорее всего, будет использована в комбинации с сеттерами и геттерами, мы и добавили в них поддержку null. Данная функция ищет совпадения по NumCode значению, и нам ничто не мешает сделать аналогичные функции для оставшихся ключей.
DataBase на SharedPreferences в действии
Перейдём в наш MainActivity и создадим экземпляр нашего класса, наименовав его db. После чего получим JSONobject из памяти Android и в функции «createDB» запишем всю интересующую нас информацию в нашу db, затем прочитаем некоторую информацию карточки в функции readInfoDB, выпишем её, следом изменим внутри лежащую информацию с помощью функции editInfoDB и снова распечатаем результаты:
Поздравляю, оно работает! (P.S. lateinit в Kotlin советуют не использовать)
Если вдруг Logcat не работает, попробуйте его перезагрузить. (Обычно такое происходит из-за нехватки мощности компьютера).
Какие могут возникнуть трудности в будущем?
Если у вас есть замечания по коду — пишите, обсудим в комментариях.
SharedPreferences. Сохранение данных в постоянное хранилище Android
SharedPreferences — постоянное хранилище на платформе Android, используемое приложениями для хранения своих настроек, например. Это хранилище является относительно постоянным, пользователь может зайти в настройки приложения и очистить данные приложения, тем самым очистив все данные в хранилище.
Для работы с данными постоянного хранилища нам понадобится экземпляр класса SharedPreferences, который можно получить у любого объекта, унаследованного от класса android.content.Context (например, Activity или Service). У объектов этих классов (унаследованных от Context) есть метод getSharedPreferences, который принимает 2 параметра:
ВНИМАНИЕ! Все модификаторы кроме MODE_PRIVATE в настоящий момент объявлены deprecated и не рекомендуются к использованию в целях безопасности. Если необходимо реализовать использование общих данных несколькими приложениями, это можно сделать через сервисы или контент-провайдеры. Подробнее можно почитать, например, здесь.
Чтобы получить значение необходимой переменной, используйте следующие методы объекта SharedPreferences:
Второй параметр — значение, которое вернется в случае если значение по ключу key отсутствует в SharedPreferences. Также, методом getAll() можно получить все доступные значения.
Чтобы записать значение переменной необходимо:
Также есть возможность удалить конкретное значение (remove(String key)) или все значения (clear())
Приведенный ниже код демонстрирует запись переменной типа String в хранилище: