为Android频繁的网络请求设置本地缓存

缓存可以减少网络请求次数,节省流量,减少出错的可能。

设置一个缓存读写类,可以读写缓存,并设置缓存文件失效时间


/**
 * 缓存服务器接收到的数据到本地,设置一个时间阈值
 * 一定时间内访问同一个连接直接从本地文件获取
 * 超过一定时间,缓存过期,需要重新从网络获取
 */
public class CacheServerResponse {
    /**
     * 设置缓存有效期是20分钟
     * 可以专门把失效时间作为一个参数,供不同失效时间场景定制缓存失效时间
     * 这个是默认缓存有效期的时间
     */
    private final static int CACHE_TIME_DEFAULT =1000*60*20;
    /**
     * 文件名为键,缓存有效时间为值,可以实现针对每一个缓存文件设置不同的有效时间
     */
    private final static HashMap<String,Integer> mMap=new HashMap<String,Integer>();
    /**
     * 缓存文件的后缀
     */
    private static final String CACHE_EXTENSION = ".ser";
    private static final String CACHE_SHARED_PREFERENCES = "cache_sharedpreferences";
    /**
     * 不带缓存时间的写缓存,就使用默认的缓存有效时间CACHE_TIME_DEFAULT
     * @param AppContext
     * @param fileName
     * @param serializableObject
     * @return
     */
    public static boolean saveObject(Context AppContext,String fileName,Serializable serializableObject) {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = AppContext.openFileOutput(fileName+CACHE_EXTENSION , AppContext.MODE_PRIVATE);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(serializableObject);
            oos.flush();
            DebugLog.v("response 文件 "+fileName+CACHE_EXTENSION +" 已缓存");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                oos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 增加一个参数,可以为每一个缓存文件设置自己的失效时间
     * @param AppContext
     * @param fileName
     * @param serializableObject
     * @param validMinutes
     * @return
     */
    public static boolean saveObject(Context AppContext,String fileName,Serializable serializableObject,int validMinutes) {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        mMap.put(fileName,validMinutes);
        try {
            fos = AppContext.openFileOutput(fileName+CACHE_EXTENSION , AppContext.MODE_PRIVATE);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(serializableObject);
            oos.flush();
            DebugLog.d("response 文件 " + fileName + CACHE_EXTENSION + " 已缓存");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                oos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
   /**
    * 读缓存
    * @param AppContext
    * @param file
    * @return
    */
    public static Serializable readObject(Context AppContext,String file) {
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = AppContext.openFileInput(file+CACHE_EXTENSION );
            ois = new ObjectInputStream(fis);
            return (Serializable) ois.readObject();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
   /**
    * 检查此文件的缓存是否已经失效
    */
    public static boolean isCacheDataFailure(Context AppContext,String cacheFileName) {
        boolean failure = false;
        int cache_time= CACHE_TIME_DEFAULT;
        if(null!=mMap.get(cacheFileName)){
            /*换算成毫秒*/
            cache_time=mMap.get(cacheFileName)*60*1000;
        }
        File data = AppContext.getFileStreamPath(cacheFileName + CACHE_EXTENSION );
        if (data.exists() && (System.currentTimeMillis() - data.lastModified()) > cache_time)
            failure = true;
        else if (!data.exists())
            failure = true;
        return failure;
    }
    /**
     * 清除所有的缓存
     * @param mContext
     */
    public static void clearAllCache(Context mContext){
        clearJsonCache(mContext);
        File filesDir = mContext.getFilesDir();
        DebugLog.v("缓存文件根路径:"+filesDir.getAbsolutePath());
        // 实现FilenameFilter接口的类实例可用于过滤器文件名
        FilenameFilter filter = new FilenameFilter() {
            // accept(File dir, String name)
            // 测试指定文件是否应该包含在某一文件列表中。
            public boolean accept(File dir, String name) {
                return name.endsWith(CACHE_EXTENSION);
            }
        };
        // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录
        String[] cacheFileList=filesDir.list(filter);
        File temp;
        for(String s:cacheFileList){
            DebugLog.v("缓存文件名:"+s);
            /*temp=new File(s);
            * 这样打开文件只是在根目录下打开了文件,并不是在缓存文件夹打开文件,所以删除缓存失败*/
            /*new File(s):/MyQuestionActivity.ser*/
            /*DebugLog.v("new File(s):"+temp.getAbsolutePath());*/
            temp = mContext.getFileStreamPath(s);
            DebugLog.v("new File(s):"+temp.getAbsolutePath());
            if(temp.delete()){
                DebugLog.v("已删除缓存文件:" + s);
            }else{
                DebugLog.v("缓存文件删除失败:" + s);
            }
        }
    }
}
然后就可以自由的读写缓存了,一个网络请求云标签的例子

/*获取所有分类信息*/
private void getAllType() {
    String url = UrlUtil.GetAllType();
    DebugLog.i("GetAllType url is " + url);
    PostJsonRequest postJsonRequest = new PostJsonRequest(Request.Method.GET, url, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            saveSessionID(response);
            Gson gson = new Gson();
            Log.i(TAG, "getAllType json请求结果:" + response);
            mAllTypeBean = gson.fromJson(response.toString(), AllTypeBean.class);
            EventBus.getDefault().post(mAllTypeBean);
           if(CacheServerResponse.saveObject(getApplicationContext(), "AllTypeBean", mAllTypeBean)){
                DebugLog.v("AllTypeBean"+"缓存成功");
            }else{
                DebugLog.v("AllTypeBean"+"缓存失败");
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e(TAG, "VolleyError:" + error.toString());
            try {
                byte[] htmlBodyBytes = error.networkResponse.data;
                Log.e(TAG, new String(htmlBodyBytes), error);
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
            ToastUtil.showShortToast(CircleActivity.this, "服务器连接异常");
        }
    });
    if(CacheServerResponse.isCacheDataFailure(getApplicationContext(),"AllTypeBean")){
        DebugLog.v("读取缓存失败,重新请求数据");
        postJsonRequest.setSendCookie(loadSessionID());
        postJsonRequest.setTag(TAG);
        client.addTask(postJsonRequest);
    }else{
        DebugLog.v("读取缓存成功,取消本次网络请求");
        AllTypeBean bean=(AllTypeBean)CacheServerResponse.readObject(getApplicationContext(),"AllTypeBean");
        if(null!=bean){
            mAllTypeBean=bean;
        }else{
            DebugLog.e("从缓存文件读取的分类信息为空");
        }
        EventBus.getDefault().post(mAllTypeBean);
    }
}

注意需要缓存的类需要实现Serializable接口

public class AllTypeBean implements Serializable {...

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值