1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/baijuncheng-open-source-tray

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 20 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 12.03.2025 12:19 63966cf

Tray — альтернатива Preferences для OHOS

Если вы читали документацию по классу Preferences, то возможно видели одно из этих предупреждений:

Примечание: Этот класс не поддерживает использование в нескольких процессах одновременно.

Поддержка многопроцессного режима никогда не работала надёжно.

Tray представляет собой упомянутый выше подход управления данными между процессами с использованием класса Data Ability. Также Tray предоставляет продвинутый API, который делает доступ к данным и их поддержку максимально простым благодаря механизму обновлений и миграций данных. Добро пожаловать в Preferences 2.0, также известный как Tray.

Возможности

  • работает в многопроцессном режиме
  • хранит простые типы данных в виде пар ключ-значение
  • автоматически сохраняет метаданные для каждого элемента (время создания, последнее обновление, ...)
  • управление вашими Preferences в модулях [TrayPreference]
  • Удаление отдельных модулей, всех модулей или [всех модулей, кроме некоторых очень важных]
  • Обновление и миграция ваших данных при переходе от одной версии приложения к другой с помощью версионированных Preferences и метода [onUpgrade()]
  • Миграция текущих данных, хранящихся в SharedPreferences, в Tray с помощью класса [SharedPreferencesImport]
  • Tray полностью протестирован на уровне юнита!
  • нет предупреждений Lint## Пример использования

Использование

Простое руководство по использованию Tray вместо Preferences в вашем проекте

Сохранение и чтение Preferences

// создайте объект доступа к предпочтениям. Это глобальные предпочтения вашего приложения.
final AppPreferences appPreferences = new AppPreferences(getContext()); // этот Preference предоставляется библиотекой бесплатно
// сохраните пару ключ-значение
appPreferences.put("ключ", "lorem ipsum");

// прочтите значение для вашего ключа. Второй параметр является значением по умолчанию (необязательный, иначе выбрасывается исключение)
final String значение = appPreferences.getString("ключ", "по умолчанию");
Log.v(TAG, "значение: " + значение); // значение: lorem ipsum

// прочтите ключ, который еще не был сохранен. Возвращает значение по умолчанию (или выбрасывает исключение без значения по умолчанию)
final String defaultValue = appPreferences.getString("ключ2", "по умолчанию");
Log.v(TAG, "значение: " + defaultValue); // значение: по умолчанию

Нет Editor, нет commit() или apply() ;wink:

Создание своего модуля предпочтений

Рекомендуется группировать предпочтения в модули вместо помещения всего в один глобальный модуль. Если вы использовали SharedPreferences ранее, возможно, вы использовали различные файлы для группировки своих предпочтений. Расширение TrayModulePreferences и помещение всех ключей внутри этого класса является рекомендованным способом поддержания чистого кода.```java // создание доступника предпочтений для модуля public class MyModulePreference extends TrayPreferences {

public static String KEY_IS_FIRST_LAUNCH = "first_launch";

public MyModulePreference(final Context context) {
    super(context, "myModule", 1);
}

}


```java
// доступ к предпочтениям своего модуля
final MyModulePreference myModulePreference = new MyModulePreference(getContext());
myModulePreference.put(MyModulePreference.KEY_IS_FIRST_LAUNCH, false);

Смотрите пример проекта для более подробной информации

Как и в случае с HarmonyOS RdbOpenCallback, TrayPreference позволяет реализовать методы для управления версионностью.

public class MyModulePreference extends TrayPreferences {

    public MyModulePreference(final Context context) {
        super(context, "myModule", 1);
    }

    @Override
    protected void onCreate(final int initialVersion) {
        super.onCreate(initialVersion);
    }

    @Override
    protected void onUpgrade(final int oldVersion, final int newVersion) {
        super.onUpgrade(oldVersion, newVersion);
    }

    @Override
    protected void onDowngrade(final int oldVersion, final int newVersion) {
        super.onDowngrade(oldVersion, newVersion);
    }
}

// TODO добавить полный пример

Перенос с Предпочтений на Tray

Для переноса значений из предпочтений вам следует создать свой модуль предпочтений. Этот модуль будет теперь хранить все ваши значения предпочтений.

public class ImportPreferences extends TrayPreferences {

    // Имя файла SharedPreferences
    private static final String SHARED_PREFERENCES_FILE_NAME = "PREF_NAME";

    // Ключ внутри SHARED_PREFERENCES_FILE_NAME
    private static final String KEY_FIRST_LAUNCH = "KEY_FIRST_LAUNCH";
```    // Имя файла SharedPreferences
    private static final String SHARED_PREFERENCES_FILE_NAME = "PREF_NAME";

    // Ключ внутри SHARED_PREFERENCES_NAME
    private static final String KEY_FIRST_LAUNCH = "KEY_FIRST_LAUNCH";

    // Новый ключ для этого модуля
    private static final String KEY_FIRST_LAUNCH_TRAY = "KEY_FIRST_LAUNCH_TRAY";

    public ImportPreferences(@NonNull Context context) {
        super(context, "myImportModule", 1);
    }

    // Вызывается только один раз при создании модуля
    @Override
    protected void onCreate(int initialVersion) {
        super.onCreate(initialVersion);

        // Создание объекта SharedPreferencesImport
        SharedPreferencesImport importPref =
            new SharedPreferencesImport(getContext(), 
                SHARED_PREFERENCES_FILE_NAME, KEY_FIRST_LAUNCH, KEY_FIRST_LAUNCH_TRAY);

        // Наконец выполнить миграцию
        migrate(importPref);
    }    // Новый ключ для этого модуля
    private static final String KEY_FIRST_LAUNCH_TRAY = "KEY_FIRST_LAUNCH_TRAY";

    public ImportPreferences(@NonNull Context context) {
        super(context, "myImportModule", 1);
    }

    // Вызывается только один раз при создании модуля
    @Override
    protected void onCreate(int initialVersion) {
        super.onCreate(initialVersion);

        // Создание объекта SharedPreferencesImport
        SharedPreferencesImport importPref =
            new SharedPreferencesImport(getContext(), SHARED_PREFERENCES_FILE_NAME,
                KEY_FIRST_LAUNCH, KEY_FIRST_LAUNCH_TRAY);

        // Наконец, выполнить миграцию
        migrate(importPref);
    }
```## Начало работы

### Добавление Tray в проект

1. Скопируйте папку `Tray/library` в корневую директорию проекта.

2. Измените файл `settings.gradle` в корне проекта и добавьте зависимость на этот модуль следующим образом:

   ```gradle
   include ':entry', ':library'
  1. Внесите изменения в зависимости от модуля в корне проекта. Например, если вы работаете с модулем entry, вам потребуется изменить файл build.gradle в модуле entry, чтобы добавить зависимость:

    implementation project(path: ':library')

Решение 2: локальная интеграция пакета har

  1. Скомпилируйте данный проект, скопируйте созданный пакет har из папки build директории Tray/library в папку lib вашего проекта: директория: \Tray\library\build\outputs\har\debug\library-debug.har

  2. Добавьте следующий код в файл gradle модуля entry:

    implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])

Решение 3: удаленная интеграция через Maven репозиторий Добавьте следующий код в файл gradle модуля entry:

implementation 'com.gitee.baijuncheng-open-source:tray:1.0.1'
```Дополнительная информация о конфигурации `Data Ability` доступна в проекте.

## Состояние проекта

Tray находится в активной разработке командой [grandcentrix]. Мы решили сделать проект открытым после достижения 100%-го покрытия тестами. [grandcentrix] использует Tray в двух приложениях в продакт-среде без проблем.

Вы можете следить за развитием проекта в ветке [`develop`].

## Покрытие тестами 100%

У Tray есть 100% покрытие тестами, и мы будем стремиться поддерживать это значение для стабильных версий.

## Избыточность Data Ability?

Начально, это был самый простой способ использовать IDL для решения проблемы многопроцессорности. Использование `Data Ability` с базой данных оказалось очень удобным для хранения метаданных. Мы рассматривали замену базы данных реальными `Preferences`, чтобы повысить производительность (Preferences не обращаются к диску при каждом чтении/записи, что решает проблему многопроцессорности). Однако метаданные оказались более ценными для нас. Смотрите [более подробную информацию].

Если вы нашли лучшее решение, реализуйте его в файле library/src/main/java/net/grandcentrix/tray/core/TrayStorage.java и сделайте свой вклад в этот проект! Мы будем благодарны за ваше участие.Сказано это, да, производительность не так хороша, как у SharedPreferences. Но она достаточно высока для синхронного сохранения/чтения одиночных пар ключ-значение. Если вам нужно сохранять больше данных, рассмотрите использование простой базы данных.

## Отсутствующие возможностиТрей готов к использованию без showblockers! Но вот некоторые полезные возможности для будущего:
- Реактивный обёртка для наблюдения за значениями
- Нет поддержки для сохранения `Set<String>`. Есть ли кто-то, кто использует это?
- Дополнительные метаданные поля: (например, версия приложения/код)

## План действий

- тесты производительности
- кэш памяти на основе ContentObservers
- предотвратить аварийное завершение работы приложения из-за ошибок базы данных
- обёртка Rx для изменений
- сохранение дополнительных типов данных (`Set<String>`, `byte[]`)

## Версии

##### Версия 0.11.1 `07.02.17`

- ключ предпочтения не может быть пустым #84
- `clearBut(TrayPreference)` -> `clearBut(AbstractTrayPreference)` #89

##### Версия 0.11.0 `07.09.16`
- все методы доступа возвращают `boolean`, указывающий на успешность операций типа `put`, `remove`. Они больше никогда не будут выбрасывать ошибки. #69
- новый метод `contains()` #74

##### Версия 0.10.0 `31.05.16`
- все функции и изменения из предварительных сборок 1.0.0-rc
- #65 Исправление удаления некорректно мигрированных общих предпочтений.

>##### Предварительная версия 1.0.0  отложена до готовности кэша памяти

>###### 1.0.0-rc3 `05.11.15`
- образец проект теперь включает способ проверки поддержки многопроцессного режима по сравнению с `SharedPreferences`
- удалены ненужные операции записи для каждого проверочного запроса #54>###### 1.0.0-rc2 `24.09.15`
- Добавлен логгинг для всех методов изменения данных. Включение через `adb shell setprop log.tag.Tray VERBOSE`

>###### 1.0.0-rc1 `21.09.15`
- Поддержка автоматического резервного копирования
    - Разделение базы данных на данные пользователя и устройства (теперь можно исключать устройство-специфичные данные из автоматического резервного копирования)
    - `TrayPreferences` теперь имеет необязательный третий параметр конструктора `TrayStorage.Type`, который может принимать значения `USER` или `DEVICE`, указывающие внутреннюю базу данных. По умолчанию значение равно `USER`
- **Новые методы и изменения**
    - `PreferenceAccessor#wipe()` очищает данные предпочтений и его внутренние данные (версию)
    - `TrayPreferences#annexModule(String name)` импортирует модуль по имени и затем очищает его. Это позволяет переименовать предпочтения без потери данных
    - `AbstractTrayPreference#annex(ModularizedStorage<TrayItem>)` позволяет одному хранилищу импортировать другое, а затем очистить импортированное
    - `Preference #onCreate(...)` и `#onUpgrade(...)` больше не являются абстрактными, так как они не требуют реализации
- **Устаревшие элементы** (будут удалены в ближайшее время)
    - `TrayAppPreferences` теперь устарел. Вместо него используйте `AppPreferences` (переименование)
    - `TrayModulePreferences` теперь устарел. Вместо него используйте `TrayPreferences` для расширения своих предпочтений
- **Внутренняя структура**
    - Новая структура пакетов.Объединены пакеты `accessor`, `migration` и `storage` в пакет `core`
     - пакет `provider` содержит реализацию `TrayStorage` с `Data Ability`. Легко заменимый другой реализацией `TrayStorage`
     - `ModularizedTrayPreference` теперь называется `AbstractTrayPreference`
     - `ModularizedStorage` переименован в `TrayStorage`##### Версия 0.9.2 `02.06.15`
 - `getContext()` работает в `TrayModulePreference#onCreate`##### Версия 0.9.1 `15.05.18`
- теперь можно сохранять `null` с помощью `mPref.put(KEY, null)`
- доступ к предпочтению с использованием методов, выбрасывающих исключения, вместо значения по умолчанию (выбрасывает ItemNotFoundException). Пример: `mPref.getString(KEY);` вместо `mPref.getString(KEY, "defaultValue");`
- WrongTypeException при доступе к предпочтению с другим типом данных, если данные не могут быть распарсированы. Преобразование типа `Float` (`10.1f`) -> `String` работает, преобразование типа `String` (`"10.1"`) -> `Float` работает, преобразование типа `String` (`"test"`) -> `Float` выбрасывает исключение!
- javadoc теперь включена в aar

##### Версия 0.9 `15.04.27`
- первая публичная версия

##### Версия 0.2 - 0.8
- рефакторинг
- тестирование 100%
- исправление ошибок

##### Версия 0.1 `14.09.17`
- первый рабочий прототип


## Вкладчики

- Pascal Welsch - https://github.com/passsy
- Jannis Veerkamp - https://github.com/jannisveerkamp

# Лицензия

Copyright 2015 grandcentrix GmbH

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.


Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/baijuncheng-open-source-tray.git
git@api.gitlife.ru:oschina-mirror/baijuncheng-open-source-tray.git
oschina-mirror
baijuncheng-open-source-tray
baijuncheng-open-source-tray
master