初次使用okgo的时候只是简单实现网络加载数据,后来慢慢发现okgo还有一个强大的功能-------
网络缓存,在没有网络的情况下可以展示数据。提高用户体验。
不过在第一次用的时候不知怎么回事一直无法实现请求是成功的但是不走
onCacheSuccess方法。
于是开始了我的okgo探索之路。首先仔细阅读了okgo网络缓存模块的介绍(https://github.com/jeasonlzy/okhttp-OkGo/wiki/Cache)
特别注意:就是下面这段话,让我呆在坑里许久。
使用缓存前,必须让涉及到缓存javaBean
对象实现Serializable
接口,否者会报NotSerializableException
。因为缓存的原理是将对象序列化后直接写入数据库中,如果不实现Serializable
接口,会导致对象无法序列化,进而无法写入到数据库中,也就达不到缓存的效果。
先上一段代码
OkGo.<CashResponse<NearByTaskModel>>get(Urls.GET_RECOMMEND) //.params("userId", 1) .cacheKey("recommend") //由于该fragment会被复用,必须保证key唯一,否则数据会发生覆盖 .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST) //缓存模式先使用缓存,然后使用网络数据 .params("userId", (int) PrefUtils.get(getContext(), "id", -1)) .params("latitude", lat)//维度 .params("longitude", lng) .params("time", time) .params("pageIndex", page) .params("pageSize", 10) .execute(new CashCallback<CashResponse<NearByTaskModel>>() {//这里去掉加载狂 @Override public void onSuccess(Response<CashResponse<NearByTaskModel>> response) { Log.e(TAG, "onSuccess: -------------------" + 1); if (response.body().errorCode == 0) { if (response.body().data.list.size() < 10) { isBottom = true;//此时说明已经到底部了 // mRefreshLayout.finishLoadMore(2000, true, true); } if (page != 0) { for (int i = 0; i < response.body().data.list.size(); i++) { datas.add(response.body().data.list.get(i)); } commomAdapter.addData(response.body().data.list); } else { datas = response.body().data.list; commomAdapter.replaceData(response.body().data.list); lv.setAdapter(commomAdapter); } } } @Override public void onCacheSuccess(Response<CashResponse<NearByTaskModel>> response) { super.onCacheSuccess(response); Log.e(TAG, "onSuccess: -------------------" + 2); if (!isInitCache) { //一般来说,缓存回调成功和网络回调成功做的事情是一样的,所以这里直接回调onSuccess onSuccess(response); isInitCache = true; } } @Override public void onError(Response<CashResponse<NearByTaskModel>> response) { super.onError(response); Log.e(TAG, "onSuccess: -------------------" + 3); } @Override public void onFinish() { super.onFinish(); if (!isBottom) { mRefreshLayout.finishLoadMore(2000); } else { mRefreshLayout.finishLoadMore(2000, true, true); } mRefreshLayout.finishRefresh(2000, true); } });
//代码中红色字体部分是你缓存能否成功的关键,不同的数据结构有着不同的写法 ,这个也可以根据okgo的demo自己去探索学习一下;
public class CashResponse<T> implements Serializable { private static final long serialVersionUID = -686453405647539973L; public int errorCode; public String message; public T data; }
public abstract class CashCallback<T> extends AbsCallback<T> { /** * 这里的数据解析是根据 http://gank.io/api/data/Android/10/1 返回的数据来写的 * 实际使用中,自己服务器返回的数据格式和上面网站肯定不一样,所以以下是参考代码,根据实际情况自己改写 */ @Override public T convertResponse(Response response) throws Throwable { //以下代码是通过泛型解析实际参数,泛型必须传 Type genType = getClass().getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); Type type = params[0]; if (!(type instanceof ParameterizedType)) throw new IllegalStateException("没有填写泛型参数"); JsonReader jsonReader = new JsonReader(response.body().charStream()); Type rawType = ((ParameterizedType) type).getRawType(); if (rawType == CashResponse.class) { // Log.e(TAG, "convertResponse: ", ); CashResponse gankResponse = Convert.fromJson(jsonReader, type); if (true) { response.close(); //noinspection unchecked return (T) gankResponse; } else { response.close(); throw new IllegalStateException("服务端接口错误"); } } else { response.close(); throw new IllegalStateException("基类错误无法解析!"); } } }
//想要成功实现缓存实体类的写法必须这样写 无需写get、和set方法直接实现Serializable接口即可
//只需生命变量就行了 。
public class NearByTaskModel implements Serializable { // private static final long serialVersionUID = -686453405647539973L; private static final long serialVersionUID = 6753210234564872868L; public int code; public String message; public List<ListBean> list; public static class ListBean implements Serializable { public int id; public int userId; public String username; public String avatar; public String title; public String content; public int typeId; public String typeName; public float price; public float distance; public String insertTime; public String imageUrl; public Object videoUrl; public int hotUpCount; public int commentCount; public int viewCount; } }