RxCache使用教程

這是一個基於 Retrofit的Reactive緩存庫,可用於Android 和Java。可以將你的緩存成需求轉成一個接口java

配置

添加JitPack倉庫在你的build.gradle文件 (項目根目錄下):react

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

添加依賴庫,在項目模塊中git

dependencies {
    compile "com.github.VictorAlbertos.RxCache:core:1.4.6"
    compile "io.reactivex:rxjava:1.1.5"
}

使用方法

定義一個接口CacheProvidergithub

public interface CacheProviders {
    //這裏設置緩存失效時間爲2分鐘。
    @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)
    Observable<Reply<List<Repo>>> getRepos(Observable<List<Repo>> oRepos, DynamicKey userName, EvictDynamicKey evictDynamicKey);

    @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)
    Observable<Reply<List<User>>> getUsers(Observable<List<User>> oUsers, DynamicKey idLastUserQueried, EvictProvider evictProvider);

    Observable<Reply<User>> getCurrentUser(Observable<User> oUser, EvictProvider evictProvider);
}
public interface RestApi {
    String URL_BASE = "https://api.github.com";
    String HEADER_API_VERSION = "Accept: application/vnd.github.v3+json";

    @Headers({HEADER_API_VERSION})
    @GET("/users")
    Observable<List<User>> getUsers(@Query("since") int lastIdQueried, @Query("per_page") int perPage);

    @Headers({HEADER_API_VERSION})
    @GET("/users/{username}/repos")
    Observable<List<Repo>> getRepos(@Path("username") String userName);

    @Headers({HEADER_API_VERSION})
    @GET("/users/{username}") Observable<Response<User>> getUser(@Path("username") String username);
}

將RestApi中須要緩存的接口方法在CacheProviders寫相應的方法,如:json

Observable<List<Repo>> getRepos(@Path("username") String userName);

對應api

Observable<Reply<List<Repo>>> getRepos(Observable<List<Repo>> oRepos, DynamicKey userName, EvictDynamicKey evictDynamicKey);

建立一個RxCache實例並使用它

最後,使用 RxCache.Builder實例化提供者interface,提供一個有效的文件系統路徑容許RxCache寫磁盤上。

//cacheDir緩存文件路徑
 ort rx.Observable;
import rx.functions.Func1;
import sample_data.cache.CacheProviders;
import sample_data.entities.Repo;
import sample_data.entities.User;
import sample_data.net.RestApi;

public class Repository {
    public static final int USERS_PER_PAGE = 25;

    public static Repository init(File cacheDir) {
        return new Repository(cacheDir);
    }

    private final CacheProviders cacheProviders;
    private final RestApi restApi;

    public Repository(File cacheDir) {
        //persistence設置爲緩存文件路徑cacheDir,using設置成你所定義的接口類class
        cacheProviders = new RxCache.Builder()
                .persistence(cacheDir)
                .using(CacheProviders.class);

        restApi = new Retrofit.Builder()
                .baseUrl(RestApi.URL_BASE)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build().create(RestApi.class);
    }
    /**
     *
     * @param update 是否更新,若是設置爲true,緩存數據將被清理,而且向服務器請求數據
     * @return
     */
    public Observable<Reply<List<User>>> getUsers(int idLastUserQueried, final boolean update) {
        //這裏設置idLastUserQueried爲DynamicKey,
        return cacheProviders.getUsers(restApi.getUsers(idLastUserQueried, USERS_PER_PAGE), new DynamicKey(idLastUserQueried), new EvictDynamicKey(update));
    }

    //對應每一個不一樣的userName,配置緩存
    public Observable<Reply<List<Repo>>> getRepos(final String userName, final boolean update) {
        //以userName爲DynamicKey,若是update爲true,將會從新獲取數據並清理緩存。
        return cacheProviders.getRepos(restApi.getRepos(userName), new DynamicKey(userName), new EvictDynamicKey(update));
    }

    public Observable<Reply<User>> loginUser(final String userName) {
        return restApi.getUser(userName).map(new Func1<Response<User>, Observable<Reply<User>>>() {
            @Override public Observable<Reply<User>> call(Response<User> userResponse) {

                if (!userResponse.isSuccess()) {
                    try {
                        ResponseError responseError = new Gson().fromJson(userResponse.errorBody().string(), ResponseError.class);
                        throw new RuntimeException(responseError.getMessage());
                    } catch (JsonParseException | IOException exception) {
                        throw new RuntimeException(exception.getMessage());
                    }
                }
                //用戶登錄,這裏設置 new EvictProvider(true),表示登錄不緩存,爲實時登錄
                return cacheProviders.getCurrentUser(Observable.just(userResponse.body()), new EvictProvider(true));
            }
        }).flatMap(new Func1<Observable<Reply<User>>, Observable<Reply<User>>>() {
            @Override public Observable<Reply<User>> call(Observable<Reply<User>> replyObservable) {
                return replyObservable;
            }
        }).map(new Func1<Reply<User>, Reply<User>>() {
            @Override public Reply<User> call(Reply<User> userReply) {
                return userReply;
            }
        });
    }

    public Observable<String> logoutUser() {
        return cacheProviders.getCurrentUser(Observable.<User>just(null), new EvictProvider(true))
                .map(new Func1<Reply<User>, String>() {
                    @Override
                    public String call(Reply<User> user) {
                        return "Logout";
                    }
                })
                .onErrorReturn(new Func1<Throwable, String>() {
                    @Override
                    public String call(Throwable throwable) {
                        return "Logout";
                    }
                });
    }

    public Observable<Reply<User>> getLoggedUser(boolean invalidate) {
        Observable<Reply<User>> cachedUser = cacheProviders.getCurrentUser(Observable.<User>just(null), new EvictProvider(false));

        Observable<Reply<User>> freshUser = cachedUser.flatMap(new Func1<Reply<User>, Observable<Reply<User>>>() {
            @Override public Observable<Reply<User>> call(Reply<User> userReply) {
                return loginUser(userReply.getData().getLogin());
            }
        });

        if (invalidate) return freshUser;
        else return cachedUser;
    }

    private static class ResponseError {
        private final String message;

        public ResponseError(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }
}

DynamicKeyGroup 的使用

interface Providers {        
    Observable<List<Mock>> getMocksPaginateWithFiltersEvictingPerFilter(Observable<List<Mock>> oMocks, DynamicKeyGroup filterPage, EvictDynamicKey evictFilter);
}
public class Repository {
    private final Providers providers;

    public Repository(File cacheDir) {
        providers = new RxCache.Builder()
                .persistence(cacheDir)
                .using(Providers.class);
    }

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

    //在實際的使用狀況下,這裏是當你創建你觀察到的與昂貴的操做。
    //若是你正在使用HTTP調用能夠改造出來的盒子。
    private Observable<List<Mock>> getExpensiveMocks() {
        return Observable.just(Arrays.asList(new Mock("")));
    }
}

Demo地址RxCacheSamples.

混淆配置

-dontwarn io.rx_cache.internal.**
相關文章
相關標籤/搜索