Сохраняем настройки
Введение
Очень часто требуется сохранить какие-то настройки. Простой пример — девочка с удовольствим пользовалась нашей программой Счётчик ворон и вертела головой в поисках очередной птицы. Но вот незадача — когда девочка вечером закрывала своё приложение, то на следующий день счётчик обнулялся. А так хотелось узнать, сколько ворон можно насчитать за месяц. Но однажды в дождливый осенний день она встретила рыжее чудо. Впрочем, это уже совсем другая история.
Самый простой способ, который приходит в голову — сбросить данные в файл, а при запуске приложения считывать необходимые данные из файла. Второй вариант — работать с базой данных и хранить настройки там.
Рассмотрим сначала второй вариант. Хранить данные в базе данных не всегда оправдано, если данных не слишком много, они простые и нам не нужно анализировать данные на предмет, сколько мышек поймал котик в прошлом году и сколько часов он спал в январе и феврале.
Первый вариант с файлами хорош, например, для сохранения больших текстовых заметок. Естественно, и для простых данных мы тоже можем использовать файлы. Записали что-то в файл, а потом открыли его и считали данные.
На самом деле нет необходимости изобретать свой велосипед и придумывать свою структуру для хранения данных. В Android существует класс SharedPreferences (Общие настройки), разработанный специально для этих целей. Приложение автоматически создаёт файл в своей папке и хранит простые данные в виде «ключ — значение». Весь процесс создания, открытия, чтения файла оптимизирован и избавляет вас от головной боли.
Общие настройки поддерживают базовые типы boolean, String, float, long и int, что делает их идеальным средством для быстрого сохранения значений по умолчанию, переменных экземпляра класса, текущего состояния UI и пользовательских настроек. Они чаще всего используются для обеспечения постоянства данных между пользовательскими сессиями и доступа к ним компонентов приложения.
Сохранение значений параметров
Если у вас сохранился старый проект по подсчёту ворон, то можете снова его открыть и добавить новый код. Либо заново создайте проект по памяти, заодно проверите, как усвоили урок и сможете ли вы самостоятельно создать проект с нуля, не заглядывая на сайт за подсказкой.
Создаём переменную, представляющую экземпляр класса SharedPreferences, который отвечает за работу с настройками:
Вы передаёте в указанный метод getSharedPreferences() имя вашего файла (файл будет создан автоматически) и стандартное разрешение по умолчанию MODE_PRIVATE — только приложение имеет доступ к настройкам. Если вам необходимо, вы можете создать несколько подобных файлов настроек.
Немного опередим события и представим, что приложение запущено, и мы считаем ворон весь день. Когда мы закрываем приложение, то нам необходимо сохранить информацию в «Общих настройках». Обычно для этих целей используют методы onPause() или onStop().
Чтобы внести изменения в настройки, нужно использовать класс SharedPreferences.Editor. Получить объект Editor можно через вызов метода edit() объекта SharedPreferences. После того, как вы внесли все необходимые изменения, вызовите метод apply(), чтобы изменения вступили в силу.
Теперь при закрытии программы значение счётчика автоматически запишется в файл. При повторном запуске приложения нам уже не нужно инициализировать счётчик со значением 0. Мы можем прочитать сохранённое значение и использовать его для счётчика, чтобы продолжить подсчёт. Сделаем это в методе onResume().
Мы проверяем сначала наличие ключа APP_PREFERENCES_COUNTER, а затем извлекаем из ключа его значение.
Вот и всё. Небольшие изменения в коде сделали программу продвинутой. Теперь вы можете спокойно закрывать и открывать программу, ваши данные не будут потеряны. При желании вы можете добавить кнопку для сброса счётчика. Это вам в качестве домашнего задания.
В теории показаны дополнительные примеры и даны подробные сведения об использовании «Общих настроек». Вам следует хорошенько разобраться в этом механизме, так как он часто используется на практике. Более того, некоторые программисты предпочитают использовать «Общие настройки» вместо базы данных, если это позволяет логика программы, так как это работает быстрее и потребляет меньше ресурсов. Выбор за вами.
Вместо послесловия
Не волнуйтесь, с котёнком всё в порядке. Девочка подобрала его и принесла домой. И добрая девочка по-прежнему пользуется нашей программой «Счётчик ворон». Наверное, биологом станет или ветеринаром.
При написании статьи использовались иллюстрации Рины З..
Источник
Android studio сохранение прогресса
В этом уроке мы научимся выполнять сохранение данных нашего приложения для того, чтобы при следующих его запусках воссоздать сохраненное, а не вводить заново. Самый, наверное, распространенный и полезный способ от такого сохранения — это сохранение логина и пароля к чему либо: аккаунту, архиву и многое другое. Хотя на паролях все возможности далеко не исчерпываются, но мы рассмотрим пример использования стандартного интерфейса Shared Preferences на примере сохранения текстовых данных. Мы сделаем Android приложение, в котором будет два поля для ввода логина и пароля (любых двух слов) и две кнопки, сохранить и загрузить. Если заполнить поля ввода, но не нажать кнопку сохранить — введенные данные будут теряться, если же перед выходом пользователь нажмет на кнопку «Сохранить» то при следующем запуске он нажмет кнопку «Загрузить» и поля автоматически заполнятся введенными и сохраненными ранее символами.
Сохранение данных с помощью Shared Preferences происходит благодаря тому, что при сохранении данных таким образом, приложение создает специальный xml файл, где будет храниться нужная информация, и при нужде получить сохраненные данные, программа будет обращаться к этому xml файлу. Файл храниться в системе устройства по адресу /data/data/НАЗВАНИЕ_ПРОЕКТА/shared_prefs.
Интерфейс для сохранения настроек Shared Preferences довольно прост в использовании. Для этого вызывается специальный метод под названием getPreferences(). По отношению к введенным данным можно выбрать 3 уровня доступности:
— MODE_PRIVATE — только это приложение может читать настройки с xml файла;
— MODE_WORLD_READABLE — все приложения могут читать с xml файла;
— MODE_WORLD_WRITEABLE — все приложения могут выполнять запись в xml файл.
После объявления метода работы с Shared Preferences нужно создать объект Editor, который нужен для создания пар имя-значение, которые будут записаны в xml файл для сохранения с помощью метода put() . Для успешного внесения данных в файл сохранения в конце нужно выполнить команду commit.
Для того, чтобы извлечь сохраненные данные, нужно обратиться к ним с помощью команды get (), ссылаясь на необходимые пары-значения.
Итак, начнем делать наше приложение, описанное вначале. Создаем новый проект, выбираем Blank Activity. Интерфейс программы будет иметь два поля для ввода текста и две кнопки. Открываем файл activity_main.xml и добавляем в него следующее:
Теперь открываем MainActivity.java и добавляем этот код (объяснения там же):
Как видите, при сохранении и загрузке сохраненных данных будет высвечиваться Toast сообщение с информацией о выполненной операции.
Теперь осталось только протестировать наше приложение:
Похоже на чудо, но оно работает!
Таким образом, в этом уроке мы научились как в Android программировании выполнять сохранение данных приложения с помощью стандартного интерфейса под названием Shared Preferences. Надеюсь у вас все получилось, удачи в начинаниях.
Также можете переходить к изучению SQLite Database.
Источник
SharedPreferences. Сохранение данных в постоянное хранилище Android
SharedPreferences — постоянное хранилище на платформе Android, используемое приложениями для хранения своих настроек, например. Это хранилище является относительно постоянным, пользователь может зайти в настройки приложения и очистить данные приложения, тем самым очистив все данные в хранилище.
Для работы с данными постоянного хранилища нам понадобится экземпляр класса SharedPreferences, который можно получить у любого объекта, унаследованного от класса android.content.Context (например, Activity или Service). У объектов этих классов (унаследованных от Context) есть метод getSharedPreferences, который принимает 2 параметра:
- name — выбранный файл настроек. Если файл настроек с таким именем не существует, он будет создан при вызове метода edit() и фиксировании изменений с помощью метода commit().
- mode — режим работы. Возможные значения:
- MODE_PRIVATE — используется в большинстве случаев для приватного доступа к данным приложением-владельцем
- MODE_WORLD_READABLE — только для чтения
- MODE_WORLD_WRITEABLE — только записи
- MODE_MULTI_PROCESS — несколько процессов совместно используют один файл SharedPreferences.
ВНИМАНИЕ! Все модификаторы кроме MODE_PRIVATE в настоящий момент объявлены deprecated и не рекомендуются к использованию в целях безопасности. Если необходимо реализовать использование общих данных несколькими приложениями, это можно сделать через сервисы или контент-провайдеры. Подробнее можно почитать, например, здесь.
Чтобы получить значение необходимой переменной, используйте следующие методы объекта SharedPreferences:
- getBoolean(String key, boolean defValue),
- getFloat(String key, float defValue),
- getInt(String key, int defValue),
- getLong(String key, long defValue),
- getString(String key, String defValue),
- getStringSet(String key, Set defValues).
Второй параметр — значение, которое вернется в случае если значение по ключу key отсутствует в SharedPreferences. Также, методом getAll() можно получить все доступные значения.
Чтобы записать значение переменной необходимо:
- получить объект SharedPreferences.Editor выполнив метод edit() объекта класса SharedPreferences
- записать значение с помощью методов:
- putBoolean(String key, boolean value),
- putFloat(String key, float value),
- putInt(String key, int value),
- putLong(String key, long value),
- putString(String key, String value),
- putStringSet(String key, Set values)
- выполнить метод commit()
Также есть возможность удалить конкретное значение (remove(String key)) или все значения (clear())
Приведенный ниже код демонстрирует запись переменной типа String в хранилище:
Источник
Настройки и состояние приложения
Сохранение состояния приложения
В одной из предыдущих тем был рассмотрен жизненный цикл Activity в приложении на Android, где после создания Activity вызывался метод onRestoreInstanceState , который восстанавливал ее состояние, а перед завершением работы вызывался метод onSaveInstanceState , который сохранял состояние Actiity. Оба этих метода в качестве параметра принимают объект Bundle , который как раз и хранит состояние activity:
В какой ситуации могут быть уместно использование подобных методов? Банальная ситуация — переворот экрана и переход от портретной ориентации к альбомной и наоборот. Если, к примеру, графический интерфейс содержит текстовое поле для вывода TextView, и мы программно изменяем его текст, то после изменения ориентации экрана его текст может исчезнуть. Или если у нас глобальные переменные, то при изменении ориентации экрана их значения могут быть сброшены до значений по умолчанию.
Чтобы точнее понять проблему, с которой мы можем столкнуться, рассмотрим пример. Изменим файл activity_main следующим образом:
Здесь определено поле EditText, в которое вводим имя. И также определена кнопка для его сохранения.
Далее для вывода сохраненного имени предназначено поле TextView, а для получения сохраненного имени — вторая кнопка.
Теперь изменим класс MainActivity :
Для хранения имени в программе определена переменная name. При нажатии на первую кнопку сохраняем текст из EditText в переменную name, а при нажатии на вторую кнопку — обратно получаем текст из переменной name в поле TextView.
Запустим приложение введем какое-нибудь имя, сохраним и получим его в TextView:
Но если мы перейдем к альбомному режиму, то TextView окажется пустым, несмотря на то, что в него вроде бы уже получили нужное значение:
И даже если мы попробуем заново получить значение из переменной name, то мы увидим, что она обнулилась:
Чтобы избежать подобных ситуаций как раз и следует сохранять и восстанавливать состояние activity. Для этого изменим код MainActivity:
В методе onSaveInstanceState() сохраняем состояние. Для этого вызываем у параметра Bundle метод putString(key, value) , первый параметр которого — ключ, а второй — значение сохраняемых данных. В данном случае мы сохраняем строку, поэтому вызываем метод putString() . Для сохранения объектов других типов данных мы можем вызвать соответствующий метод:
put() : универсальный метод, который добавляет значение типа Object. Соответственно поле получения данное значение необходимо преобразовать к нужному типу
putString() : добавляет объект типа String
putInt() : добавляет значение типа int
putByte() : добавляет значение типа byte
putChar() : добавляет значение типа char
putShort() : добавляет значение типа short
putLong() : добавляет значение типа long
putFloat() : добавляет значение типа float
putDouble() : добавляет значение типа double
putBoolean() : добавляет значение типа boolean
putCharArray() : добавляет массив объектов char
putIntArray() : добавляет массив объектов int
putFloatArray() : добавляет массив объектов float
putSerializable() : добавляет объект интерфейса Serializable
putParcelable() : добавляет объект Parcelable
Каждый такой метод также в качестве первого параметра принимает ключа, а в качестве второго — значение.
В методе onRestoreInstanceState происходит обратный процесс — с помощью метода getString(key) по ключу получаем из сохраненного состояния строку по ключу. Соответственно для получения данных других типов мы можем использовать аналогичные методы:
get() : универсальный метод, который возвращает значение типа Object. Соответственно поле получения данное значение необходимо преобразовать к нужному типу
getString() : возвращает объект типа String
getInt() : возвращает значение типа int
getByte() : возвращает значение типа byte
getChar() : возвращает значение типа char
getShort() : возвращает значение типа short
getLong() : возвращает значение типа long
getFloat() : возвращает значение типа float
getDouble() : возвращает значение типа double
getBoolean() : возвращает значение типа boolean
getCharArray() : возвращает массив объектов char
getIntArray() : возвращает массив объектов int
getFloatArray() : возвращает массив объектов float
getSerializable() : возвращает объект интерфейса Serializable
getParcelable() : возвращает объект Parcelable
Для примера рассмотрим сохранение-получение более сложных данных. Например, объектов определенного класса. Пусть у нас есть класс User :
Класс User реализует интерфейс Serializable , поэтому мы можем сохранить его объекты с помощью метода putSerializable() , а получить с помощью метода getSerializable() .
Пусть у нас будет следующий интерфейс в activity_main.xml :
Здесь определены два поля ввода для имени и возраста соответственно.
В классе MainActivity пропишем логику сохранения и получения данных:
Здесь также сохраняем данные в переменную User, которая предварительно инициализированна некоторыми данными по умолчанию. А при нажатии на кнопку получения получем данные из переменной и передаем их для вывода в текстовое поле.
Источник