Аннотация @ProviderKey — это защита данных пользователя метода Provider. Настоятельно рекомендуется использовать эту аннотацию! Если не использовать эту аннотацию, то имя метода будет использоваться как ключ для кэширования файла. Если используется обфускация кода, то пользователи быстро столкнутся с проблемами. Подробнее см. Proguard. Даже если не используется обфускация, эта аннотация полезна, так как она гарантирует, что вы можете свободно изменять имена методов данных провайдера без необходимости беспокоиться о проблемах переноса старых файлов кэша.
Эта аннотация была добавлена недавно и учитывает обфускацию кода (изменение имён методов приводит к изменению имён файлов кэша) и перенос данных кэша. Настоятельно рекомендуем использовать эту аннотацию!
EvictDynamicKey — удаляет ли конкретные данные кэша DynamicKey. Область удаления данных кэша меньше, чем EvictProvider (который удаляет все данные кэша), больше, чем EvictDynamicKeyGroup (который удаляет более детализированные данные кэша). Например, если передать userId (уникальный) в качестве параметра в DynamicKey, при очистке кэша будут удалены только соответствующие данные кэша для этого userId.
EvictDynamicKeyGroup — удаляет ли более конкретные данные кэша DynamicKeyGroup. По сравнению с EvictDynamicKey, в этом примере DynamicKeyGroup может фильтровать данные кэша одной страницы для данного userId для удаления, а другие данные кэша не удаляются.
DynamicKey — связывает данные кэша с переданным объектом (например, userId) и очищает связанные данные кэша, используя EvictDynamicKey.
DynamicKeyGroup — связывает данные кэша с переданной группой (например, userId, категория данных) и очищает связанные данные кэша, используя EvictDynamicKeyGroup.
Поддерживаемые аннотации:
Наконец, используйте RxCache.Builder для создания экземпляра интерфейса Provider и предоставьте действительный путь файловой системы, который позволит RxCache записывать данные кэша на диск.
// Получение пути хранения кэша в файле
File cacheDir = getFilesDir();
Providers providers = new RxCache.Builder()
.persistence(cacheDir, new GsonSpeaker()) // Настройка пути хранения кэша в файле, а также сериализации и десериализации данных
.using(Providers.class); // Аналогично Retrofit, передаём интерфейс API кэша
interface Providers {
// Настройка данных, которые нужно кэшировать, и следует ли удалять данные кэша и запрашивать сеть
@ProviderKey("mocks-evict-provider")
Observable<List<Mock>> getMocksEvictProvider(Observable<List<Mock>> oMocks, EvictProvider evictProvider);
// Настройка данных, которые необходимо кэшировать, простая классификация данных кэша, и следует ли удалять эту классификацию данных кэша и запрашивать сеть
@ProviderKey("mocks-paginate-evict-per-page")
Observable<List<Mock>> getMocksPaginateEvictingPerPage(Observable<List<Mock>> oMocks, DynamicKey page, EvictDynamicKey evictPage);
// Настройка данных, которые необходимо кэшировать, сложная классификация данных кэша, и следует ли удалять эти подробные данные классификации кэша и запрашивать сеть
@ProviderKey("mocks-paginate-evict-per-filter")
Observable<List<Mock>>
``` ```
getMocksPaginateWithFiltersEvictingPerFilter(Observable<List<Mock>> oMocks, DynamicKeyGroup filterPage, EvictDynamicKey evictFilter);
}
public class Repository {
private final Providers providers;
//初始化RxCache的Provider
public Repository(File cacheDir) {
providers = new RxCache.Builder()
.persistence(cacheDir, new GsonSpeaker())
.using(Providers.class);
}
//参数update:是否加载最新数据
public Observable<List<Mock>> getMocks(final boolean update) {
return providers.getMocksEvictProvider(getExpensiveMocks(), new EvictProvider(update));
}
//параметр page: данные какой страницы, update: следует ли загружать данные этой страницы
public Observable<List<Mock>> getMocksPaginate(final int page, final boolean update) {
return providers.getMocksPaginateEvictingPerPage(getExpensiveMocks(), new DynamicKey(page), new EvictDynamicKey(update));
}
//параметры filter: определённое условие (например, userName), page: данные какой страницы, updateFilter: следует ли обновлять данные этой страницы в соответствии с условием
public Observable<List<Mock>> getMocksWithFiltersPaginate(final String filter, final int page, final boolean updateFilter) {
return providers.getMocksPaginateWithFiltersEvictingPerFilter(getExpensiveMocks(), new DynamicKeyGroup(filter, page), new EvictDynamicKey(updateFilter));
}
//Этот метод возвращает значение, которое заменяет реальные данные, полученные через дорогостоящие операции (например, Observable<T>)
//Если здесь вы использовали Retrofit для сетевых запросов, то это можно назвать готовым к использованию.
private Observable<List<Mock>> getExpensiveMocks() {
return Observable.just(Arrays.asList(new Mock("")));
}
}
Следующие примеры использования иллюстрируют некоторые распространённые ситуации, которые помогут вам понять использование классов DynamicKey и DynamicKeyGroup, а также очистку данных.
Не очищать данные
Observable<List<Mock>> getMocks(Observable<List<Mock>> oMocks);
Очистить данные
Observable<List<Mock>> getMocksEvictProvider(Observable<List<Mock>> oMocks, EvictProvider evictProvider);
В бизнес-коде используется:
//При получении Observable данные этого Provider будут очищены, и будет сделан новый запрос
getMocksEvictProvider(oMocks, new EvictProvider(true))
//Эта строка вызовет исключение IllegalArgumentException: «Предоставлен EvictDynamicKey, но не предоставлен никакой DynamicKey»
getMocksEvictProvider(oMocks, new EvictDynamicKey(true))
Указать определённое условие, не очищать данные кэша, соответствующие этому условию
Observable<List<Mock>> getMocksFiltered(Observable<List<Mock>> oMocks, DynamicKey filter);
Указать определённое условие и выбрать, следует ли очищать данные кэша, соответствующие этому условию
Observable<List<Mock>> getMocksFilteredEvict(Observable<List<Mock>> oMocks, DynamicKey filter, EvictProvider evictDynamicKey);
Используется в бизнес-коде:
//При получении Observable данные этого Provider будут очищены и будет сделан новый запрос
getMocksFilteredEvict(oMocks, new DynamicKey("actives"), new EvictProvider(true))
//Используя EvictDynamicKey, при получении Observable данные DynamicKey («actives») будут очищены, и будет сделан новый запрос
getMocksFilteredEvict(oMocks, new DynamicKey("actives"), new EvictDynamicKey(true))
//Эта строка вызовет исключение IllegalArgumentException: «предоставлен EvictDynamicKeyGroup, но не предоставлено никаких DynamicKeyGroup»
getMocksFilteredEvict(oMocks, new DynamicKey("actives"), new EvictDynamicKeyGroup(true))
Разбиение на страницы данных List и их фильтрация, без очистки данных кэша
Observable<List<Mock>> getMocksFilteredPaginate(Observable<List<Mock>> oMocks, DynamicKey filterAndPage);
Разбиение на страницы данных List и их фильтрация с опцией очистки данных кэша
Observable<List<Mock>> getMocksFilteredPaginateEvict(Observable<List<Mock>> oMocks, DynamicKeyGroup filterAndPage, EvictProvider evictProvider);
Использование во время выполнения:
//При получении Observable данные этого Provider будут очищены, и будет сделан новый запрос
getMocksFilteredPaginateEvict(oMocks, new DynamicKeyGroup("actives", "page1"), new EvictProvider(true))
//Используя EvictDynamicKey, при получении Observable данные DynamicKey ("actives", "page1") будут очищены, и будет сделан новый запрос
getMocksFilteredPaginateEvict(oMooks, new DynamicKeyGroup("actives", "page1"), new EvictDynamicKey(true))
//Используя EvictDynamicKey, при получении Observable данные DynamicKeyGroup ("actives", "page1") будут очищены, и будет сделан новый запрос
getMocksFilteredPaginateInvalidate(oMocks, new DynamicKeyGroup("actives", "page1"), new EvictDynamicKeyGroup(true))
Как видно из кода, основное внимание при использовании классов «DynamicKey», «DynamicKeyGroup», а также «EvictProvider» уделяется очистке данных кэша в зависимости от различных диапазонов. Только когда в используемом вами классе RxCache структура данных изменилась, необходимо добавить новую миграцию.
Например, если у вас есть данные в кэше User, и там было свойство int userId, а в новой версии стало long userId, то при десериализации данных возникнет проблема. Поэтому вам нужно настроить миграцию.
Если вы удалите класс или поле класса, RxCache обработает это автоматически, поэтому при удалении поля или всего класса не нужно добавлять новую миграцию.
Сейчас класс Mock был удалён из проекта, поэтому на него нельзя ссылаться. Чтобы решить эту проблему, просто удалите соответствующую строку с миграцией.
Поскольку RxCache требует внутреннего процесса для очистки памяти, данные будут полностью очищены.
RxCache предоставляет простой механизм для шифрования данных. Вам нужно добавить аннотацию @EncryptKey к вашему интерфейсу Provider. Эта аннотация принимает строку в качестве ключа, необходимого для шифрования/дешифрования данных. Однако вам также нужно использовать аннотацию @Encrypt для аннотирования кэша Provider, чтобы данные были зашифрованы. Если вы не установите @Encrypt, шифрование не будет выполнено.
Важно отметить, что если предоставленный ключ @EncryptKey будет изменён во время компиляции, старые данные кэша не смогут быть удалены или получены RxCache.
@EncryptKey("myStrongKey-1234")
interface Providers {
@Encrypt
Observable<List<Mock>> getMocksEncrypted(Observable<List<Mock>> oMocks);
Observable<List<Mock>> getMocksNotEncrypted(Observable<List<Mock>> oMocks);
}
RxCache позволяет установить некоторые параметры при создании экземпляра Provider:
По умолчанию RxCache ограничивает размер до 100 МБ, но вы можете изменить это значение, вызвав метод setMaxMBPersistenceCache при построении экземпляра Provider.
Когда этот предел будет достигнут, RxCache больше не сможет сохранять данные. Именно поэтому, когда объём данных в кэше приближается к порогу, RxCache имеет автоматизированный процесс для удаления любых записей, даже если данные не соответствуют времени истечения срока действия.
Единственное исключение — если метод вашего Provider аннотирован @Expirable и его значение установлено в false, данные будут сохранены и не будут удалены RxCache.
По умолчанию, если данные в кэше устарели и observable loader возвращает пустые данные, RxCache выдаст исключение RuntimeException. Вы можете изменить это поведение, разрешив RxCache предоставлять удалённые данные в этом случае. Это делается путём установки значения useExpiredDataIfLoaderNotAvailable в true:
Чтобы создать экземпляр интерфейса, предоставляемого RxCache, вам необходимо предоставить ссылку на файловую систему. На Android вы можете получить эту ссылку, вызвав getFilesDir() из класса Application. Кроме того, рекомендуется использовать этот класс приложения Android для предоставления единственного экземпляра RxCache (глобальный синглтон) в течение всего жизненного цикла приложения.
Для выполнения Observable в дочернем потоке и отправки результатов через основной поток UI, используйте встроенные методы, предоставляемые RxAndroid.
Вы можете посмотреть демонстрационный пример: Android example.
RxCache идеально сочетается с Retrofit, позволяя реализовать полное автоматическое управление кэшем базы данных от начала до конца. Вы можете проверить пример использования RxCache с Retrofit.
Источник данных RxCache зависит от одного из трёх слоёв данных:
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )