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

OSCHINA-MIRROR/mirrors-RxCache

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README_ZH.md 20 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 30.11.2024 19:05 2c7125f

Аннотация @ProviderKey — это защита данных пользователя метода Provider. Настоятельно рекомендуется использовать эту аннотацию! Если не использовать эту аннотацию, то имя метода будет использоваться как ключ для кэширования файла. Если используется обфускация кода, то пользователи быстро столкнутся с проблемами. Подробнее см. Proguard. Даже если не используется обфускация, эта аннотация полезна, так как она гарантирует, что вы можете свободно изменять имена методов данных провайдера без необходимости беспокоиться о проблемах переноса старых файлов кэша.

Эта аннотация была добавлена недавно и учитывает обфускацию кода (изменение имён методов приводит к изменению имён файлов кэша) и перенос данных кэша. Настоятельно рекомендуем использовать эту аннотацию!

  • EvictDynamicKey — удаляет ли конкретные данные кэша DynamicKey. Область удаления данных кэша меньше, чем EvictProvider (который удаляет все данные кэша), больше, чем EvictDynamicKeyGroup (который удаляет более детализированные данные кэша). Например, если передать userId (уникальный) в качестве параметра в DynamicKey, при очистке кэша будут удалены только соответствующие данные кэша для этого userId.

  • EvictDynamicKeyGroup — удаляет ли более конкретные данные кэша DynamicKeyGroup. По сравнению с EvictDynamicKey, в этом примере DynamicKeyGroup может фильтровать данные кэша одной страницы для данного userId для удаления, а другие данные кэша не удаляются.

  • DynamicKey — связывает данные кэша с переданным объектом (например, userId) и очищает связанные данные кэша, используя EvictDynamicKey.

  • DynamicKeyGroup — связывает данные кэша с переданной группой (например, userId, категория данных) и очищает связанные данные кэша, используя EvictDynamicKeyGroup.

Поддерживаемые аннотации:

  • @LifeCache — устанавливает срок действия кэша. Если @LifeCache не установлена, данные будут кэшироваться навсегда, пока вы не используете EvictProvider, EvictDynamicKey или EvictDynamicKeyGroup.
  • @Actionable — предоставляет простой способ выполнения операций записи с использованием провайдера. Подробности см. здесь.
  • @SchemeMigration и @Migration — предоставляют простой механизм обработки миграции между версиями. Подробности см. здесь.
  • @Expirable — определяет, будет ли этот провайдер исключён из диапазона очистки. Подробности см. здесь.
  • @EncryptKey и @Encrypt — предоставляют простой способ шифрования/дешифрования данных на постоянном уровне. Подробности см. здесь.

Создание экземпляра Provider и его использование

Наконец, используйте 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("")));
    }
}

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

  • Использование классического API RxCache для операций чтения и записи файлов.
  • Использование Actionable API, предназначенного для операций записи файлов.

API RxCache

Следующие примеры использования иллюстрируют некоторые распространённые ситуации, которые помогут вам понять использование классов DynamicKey и DynamicKeyGroup, а также очистку данных.

EvictProvider: очистка данных кэша

Не очищать данные

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))

DynamicKey: фильтрация данных

Указать определённое условие, не очищать данные кэша, соответствующие этому условию

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))

DynamicKeyGroup: разбиение на страницы и фильтрация

Разбиение на страницы данных 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:

Замечания по использованию на Android

Чтобы создать экземпляр интерфейса, предоставляемого RxCache, вам необходимо предоставить ссылку на файловую систему. На Android вы можете получить эту ссылку, вызвав getFilesDir() из класса Application. Кроме того, рекомендуется использовать этот класс приложения Android для предоставления единственного экземпляра RxCache (глобальный синглтон) в течение всего жизненного цикла приложения.

Для выполнения Observable в дочернем потоке и отправки результатов через основной поток UI, используйте встроенные методы, предоставляемые RxAndroid.

Вы можете посмотреть демонстрационный пример: Android example.

Совместное использование с Retrofit

RxCache идеально сочетается с Retrofit, позволяя реализовать полное автоматическое управление кэшем базы данных от начала до конца. Вы можете проверить пример использования RxCache с Retrofit.

Принцип работы RxCache

Источник данных RxCache зависит от одного из трёх слоёв данных:

  • Слой памяти — поддерживается Apache ReferenceMap.
  • Постоянный слой — RxCache использует Jolyglot для сериализации и десериализации объектов.

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

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

1
https://api.gitlife.ru/oschina-mirror/mirrors-RxCache.git
git@api.gitlife.ru:oschina-mirror/mirrors-RxCache.git
oschina-mirror
mirrors-RxCache
mirrors-RxCache
2.x