retrofit2.0增加先读缓存后请求网络的功能

来源:互联网 发布:各省外商直接投资数据 编辑:程序博客网 时间:2024/06/03 12:39

由于前段时间升级了retrofit版本到了2.1,导致原来写的缓存框架出现了点问题,后来在github上看到一个smartCache缓存框架

而其版本是2.0beta版和正式版有点差距,于是就自己更改了一下框架代码,现在分享给大家


项目只有6个类

AndroidExecutor:线程池里面封装了一个handler为了post数据到主线程种

CachingSystem:接口里面就两方法存缓存以及获取缓存

BasicCaching:CachingSystem对应的实现类,实现了存取缓存方法,使用的是LruCache以及DiskLruCache算法对其进行缓存

SmartCall:自定义的一个回调接口,要使用这个框架就必须使用这个回调而不是retrofit对应的Call

SmartUtils:工具类,主要是用来把网络数据转化成byte数据,数据转成byte

SmartCallFactory:关键类,所有的逻辑都在里面

主要讲解一下SmartCallFactory这个类

public class SmartCallFactory extends CallAdapter.Factory {    //缓存类    private final CachingSystem cachingSystem;    //线程池    private final Executor asyncExecutor;    public SmartCallFactory(CachingSystem cachingSystem){        this.cachingSystem = cachingSystem;        this.asyncExecutor = new AndroidExecutor();    }    public SmartCallFactory(CachingSystem cachingSystem, Executor executor){        this.cachingSystem = cachingSystem;        this.asyncExecutor = executor;    }    @Override    public CallAdapter<SmartCall<?>> get(final Type returnType, final Annotation[] annotations,                                         final Retrofit retrofit) {        TypeToken<?> token = TypeToken.of(returnType);        //如果不是对应的SmartCall则不会执行        if (token.getRawType() != SmartCall.class) {            return null;        }        if (!(returnType instanceof ParameterizedType)) {            //必须有实体类            throw new IllegalStateException(                    "SmartCall must have generic type (e.g., SmartCall<ResponseBody>)");        }        //获得SmartCall<T>中的类型        final Type responseType = ((ParameterizedType) returnType).getActualTypeArguments()[0];        final Executor callbackExecutor = asyncExecutor;        return new CallAdapter<SmartCall<?>>() {            @Override            public Type responseType() {                return responseType;            }            @Override            public <R> SmartCall<R> adapt(Call<R> call) {                return new SmartCallImpl<>(callbackExecutor, call, responseType(), annotations,                        retrofit, cachingSystem);            }        };    }    /**     * 自定义一个回调实例     * 所有的逻辑都是在这里面     * @param <T>     */    static class SmartCallImpl<T> implements SmartCall<T>{        private final Executor callbackExecutor;        private final Call<T> baseCall;        private final Type responseType;        private final Annotation[] annotations;        private final Retrofit retrofit;        private final CachingSystem cachingSystem;        private final Request request;        public SmartCallImpl(Executor callbackExecutor, Call<T> baseCall, Type responseType,                             Annotation[] annotations, Retrofit retrofit, CachingSystem cachingSystem){            this.callbackExecutor = callbackExecutor;            this.baseCall = baseCall;            this.responseType = responseType;            this.annotations = annotations;            this.retrofit = retrofit;            this.cachingSystem = cachingSystem;            // This one is a hack but should create a valid Response (which can later be cloned)            this.request = buildRequestFromCall();        }        /***         * 构建一个新的请求         * 这里使用的反射机制         * * @return A valid Request (that contains query parameters, right method and endpoint)         */        private Request buildRequestFromCall(){            try {                Field argsField = baseCall.getClass().getDeclaredField("args");                argsField.setAccessible(true);                Object[] args = (Object[]) argsField.get(baseCall);                //retrofit2.0更改了字段(1.0+)requestFactory-->(2.0+)serviceMethod                Field serviceMethodField = baseCall.getClass().getDeclaredField("serviceMethod");                serviceMethodField.setAccessible(true);                Object requestFactory = serviceMethodField.get(baseCall);                //retrofit2.0更改了方法(1.0+)create-->(2.0+)toRequest                Method createMethod = requestFactory.getClass().getDeclaredMethod("toRequest", Object[].class);                createMethod.setAccessible(true);                return (Request) createMethod.invoke(requestFactory, new Object[]{args});            }catch(Exception exc){//                Log.e("buildRequestFromCall"+exc.toString());                return null;            }        }        public void enqueueWithCache(final Callback<T> callback) {            Runnable enqueueRunnable = new Runnable() {                @Override                public void run() {                    /* 读取缓存 */                    byte[] data = cachingSystem.getFromCache(buildRequest());                    if(data != null) {                        //获得缓存数据                        final T convertedData = SmartUtils.bytesToResponse(retrofit, responseType, annotations,                                data);                        Runnable cacheCallbackRunnable = new Runnable() {                            @Override                            public void run() {                                //存在数据直接回调给调用者,                                callback.onResponse(baseCall, Response.success(convertedData));                            }                        };                        callbackExecutor.execute(cacheCallbackRunnable);                    }                    /* 运行网络请求 */                    baseCall.enqueue(new Callback<T>() {                        @Override                        public void onResponse(final Call<T> call,final Response<T> response) {                            Runnable responseRunnable = new Runnable() {                                @Override                                public void run() {                                    if (response.isSuccessful()) {                                        //保存数据                                        byte[] rawData = SmartUtils.responseToBytes(retrofit, response.body(),                                                responseType(), annotations);                                        cachingSystem.addInCache(response, rawData);                                    }                                    //再一次回调给调用者                                    callback.onResponse(call, response);                                }                            };                            // Run it on the proper thread                            callbackExecutor.execute(responseRunnable);                        }                        @Override                        public void onFailure(final Call<T> call, final Throwable t) {                            Runnable failureRunnable = new Runnable() {                                @Override                                public void run() {                                    callback.onFailure(call,t);                                }                            };                            callbackExecutor.execute(failureRunnable);                        }                    });                }            };            Thread enqueueThread = new Thread(enqueueRunnable);            enqueueThread.start();        }        @Override        public void enqueue(final Callback<T> callback) {            if(buildRequest().method().equals("GET")){                //只对GET请求有用                enqueueWithCache(callback);            }else{                //其他的请求和retrofit一样                baseCall.enqueue(new Callback<T>() {                    @Override                    public void onResponse(final Call<T> call, final Response<T> response) {                        callbackExecutor.execute(new Runnable() {                            @Override                            public void run() {                                callback.onResponse(call,response);                            }                        });                    }                    @Override                    public void onFailure(final Call<T> call, final Throwable t) {                        callbackExecutor.execute(new Runnable() {                            @Override                            public void run() {                                callback.onFailure(call,t);                            }                        });                    }                });            }        }        @Override        public Type responseType() {            return responseType;        }        @Override        public Request buildRequest() {            return request.newBuilder().build();        }        @Override        public SmartCall<T> clone() {            return new SmartCallImpl<>(callbackExecutor, baseCall.clone(), responseType(),                    annotations, retrofit, cachingSystem);        }        @Override        public Response<T> execute() throws IOException {            return baseCall.execute();        }        @Override        public void cancel() {            baseCall.cancel();        }    }}
里面的我加入详细注释,应该很容易看懂

主要就是在自定义的SmartCallFactory的call实例中自己改写了请求回调的方式,先看缓存中是否有数据,

有直接回调给调用者,请求数据成功后也会回调给调用者,而对应的使用方法为

Retrofit client = new Retrofit.Builder()        .baseUrl(HOST)        .client(okHttpClient)        .addConverterFactory(GsonConverterFactory.create(gson))        .addCallAdapterFactory(smartFactory)        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())        .build();mGuDong = client.create(MeoHttp.class);
构建retrofit时应增加一个自定义的CallAdapterFactory

接口调用则为

/** * 获得图片列表 */@GET("tnfs/api/list")SmartCall<ImageListBean> getImageList();
使用自定义的SmartCall

其他的使用方法和retrofit一致

demo地址:github记得star给星,如若有问题请留言或者在github上提issue




1 0