【Android】Jetpack全组件实战开发短视频应用App(七)

前言

项目地址
上一篇简单说完Room创建数据库之后,这一篇主要是说下Room实现网络缓存

实现

缓存方式

/**
     * 仅仅只访问本地缓存,即便本地缓存不存在,也不会发起网络请求
     */
    public static final int CACHE_ONLY = 1;
    /**
     * 先访问缓存,同时发起网络的请求,成功后缓存到本地
     */
    public static final int CACHE_FIRST = 2;
    /**
     * 仅仅只访问服务器,不存任何存储
     */
    public static final int NET_ONLY = 3;
    /**
     * 先访问网络,成功后缓存到本地
     */
    public static final int NET_CACHE = 4;

    @IntDef({CACHE_ONLY, CACHE_FIRST, NET_CACHE, NET_ONLY})
    @Retention(RetentionPolicy.SOURCE)
    public @interface CacheStrategy {
    }

这里我们暂时定义这4中缓存方式,同时我们在Request中添加一个这是缓存类型的方法

  public R cacheStrategy(@CacheStrategy int cacheStrategy) {
        mCacheStrategy = cacheStrategy;
        return (R) this;
    }

缓存管理

接着我们定义一个缓存管理类CacheManager,里面定义保存缓存,获取缓存,删除缓存这几个方法

  /**
 * 缓存管理类
 */
public class CacheManager {

    /**
     * 反序列,把二进制数据转换成java object对象
     */
    private static Object toObject(byte[] data) {
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            bais = new ByteArrayInputStream(data);
            ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bais != null) {
                    bais.close();
                }
                if (ois != null) {
                    ois.close();
                }
            } catch (Exception ignore) {
                ignore.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 序列化存储数据需要转换成二进制
     */
    private static <T> byte[] toByteArray(T body) {
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(body);
            oos.flush();
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
                if (oos != null) {
                    oos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return new byte[0];
    }

    /**
     * 删除缓存
     */
    public static <T> void delete(String key, T body) {
        Cache cache = new Cache();
        cache.key = key;
        cache.data = toByteArray(body);
        CacheDatabase.get().getCache().deleteItem(cache);
    }

    /**
     * 保存缓存
     */
    public static <T> void save(String key, T body) {
        Cache cache = new Cache();
        cache.key = key;
        cache.data = toByteArray(body);

        CacheDatabase.get().getCache().insertItem(cache);
    }

    /**
     * 根据key获取缓存
     */
    public static Object getCache(String key) {
        Cache cache = CacheDatabase.get().getCache().getCache(key);
        if (cache != null && cache.data != null) {
            return toObject(cache.data);
        }
        return null;
    }
}

这里我们需要在我们的CacheDatabase类中添加一个获取CacheDao的方法,我们要借助这个CacheDao类来实现缓存的增删改查

public abstract CacheDao getCache();

处理网络请求

首先我们在Request类中的parseResponse方法中保存缓存


        if (mCacheStrategy != NET_ONLY && result.success && result.body != null && result.body instanceof Serializable) {
            saveCache(result.body);
        }

保存缓存的时候需要一个key,如果这个key是个空的话,那么我们就自动生成一个key,生成规则就是用urlparams

	private void saveCache(T body) {
        String key = TextUtils.isEmpty(cacheKey) ? generateCacheKey() : cacheKey;
        CacheManager.save(key, body);
    }

    private String generateCacheKey() {
        cacheKey = UrlCreator.createUrlFromParams(mUrl, mParams);
        return cacheKey;
    }

接着就是同步和异步回调内判断是否需要缓存,如果需要,我们就取缓存数据,这里先写一个方法,把缓存数据组装成我们统一返回格式的ApiReponse

 		private ApiResponse<T> readCache() {
        String key = TextUtils.isEmpty(cacheKey) ? generateCacheKey() : cacheKey;
        Object cache = CacheManager.getCache(key);
        ApiResponse<T> result = new ApiResponse<>();
        result.status = 304;
        result.message = "缓存获取成功";
        result.body = (T) cache;
        result.success = true;
        return result;
    }

然后就是改造下同步和异步的返回

  public ApiResponse<T> execute() {
        if (mType == null) {
            throw new RuntimeException("同步方法,response 返回值 类型必须设置");
        }

        if (mCacheStrategy == CACHE_ONLY) {
            return readCache();
        }

        ApiResponse<T> result = null;
        try {
            Response response = getCall().execute();
            result = parseResponse(response, null);
        } catch (IOException e) {
            e.printStackTrace();
            if (result == null) {
                result = new ApiResponse<>();
                result.message = e.getMessage();
            }
        }
        return result;
    }
 @SuppressLint("RestrictedApi")
    public void execute(final JsonCallback callback) {
        if (mCacheStrategy != NET_ONLY) {
            ArchTaskExecutor.getIOThreadExecutor().execute(new Runnable() {
                @Override
                public void run() {
                    ApiResponse<T> response = readCache();
                    if (callback != null && response.body != null) {
                        callback.onCacheSuccess(response);
                    }
                }
            });
        }
        if (mCacheStrategy != CACHE_ONLY) {
            getCall().enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    ApiResponse<T> result = new ApiResponse<>();
                    result.message = e.getMessage();
                    callback.onError(result);
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    ApiResponse<T> result = parseResponse(response, callback);
                    if (!result.success) {
                        callback.onError(result);
                    } else {
                        callback.onSuccess(result);
                    }
                }
            });
        }
    }

猜你喜欢

转载自blog.csdn.net/Greathfs/article/details/105750280