OSChinaclient源代码学习(2)--缓存的设计

一、缓存的作用

请求数据的时候,首先进行推断,能否够从缓存中获取数据,假设满足条件,则直接从缓存中获取数据。否则请求新的数据。这样比没有缓存的情况下。每次都要从server请求数据要快,并且。没有网的情况下。也能够浏览已经缓存了的数据,极大的提高了用户的体验。

二、源代码解析

源代码中用到缓存的地方有:

1 请求数据之前。先推断能否够从缓存中获取,假设满足条件,则直接从缓存中读取。否则,向server请求新的数据。

// 获取缓存的文件夹
 private String getCacheKey() {
       return new StringBuilder(getCacheKeyPrefix()).append("_")
                .append(mCurrentPage).toString();
}

// 请求数据,推断能否够从缓存中获取数据
 protected void requestData(boolean refresh) {
        String key = getCacheKey();
        if (isReadCacheData(refresh)) {
            readCacheData(key);
        } else {
            // 取新的数据
            sendRequestData();
        }
    }


//推断是否须要读缓存数据
  protected boolean isReadCacheData(boolean refresh) {
        String key = getCacheKey();
        if (!TDevice.hasInternet()) {
            return true;
        }
        // 第一页若不是主动刷新,且缓存存在,优先取缓存的
        if (CacheManager.isExistDataCache(getActivity(), key) && !refresh
                && mCurrentPage == 0) {
            return true;
        }
        // 其它页数的,缓存存在以及还没有失效,优先取缓存的
        if (CacheManager.isExistDataCache(getActivity(), key)
                && !CacheManager.isCacheDataFailure(getActivity(), key)
                && mCurrentPage != 0) {
            return true;
        }

        return false;
    }

2 对从server中获取的最新数据进行保存到缓存的操作

private class SaveCacheTask extends AsyncTask<Void, Void, Void> {
        private final WeakReference<Context> mContext;
        private final Serializable seri;
        private final String key;

        private SaveCacheTask(Context context, Serializable seri, String key) {
            mContext = new WeakReference<Context>(context);
            this.seri = seri;
            this.key = key;
        }

        @Override
        protected Void doInBackground(Void... params) {
            CacheManager.saveObject(mContext.get(), seri, key);
            return null;
        }
    }

当中saveObject方法实现例如以下

public static boolean saveObject(Context context, Serializable ser, String file) {

    FileOutputStream fos = null;
    ObjectOutputStream oos = null;
    try {
        fos = context.openFileOutput(file, Context.MODE_PRIVATE);
        oos = new ObjectOutputStream(fos);
        oos.writeObject(ser);
        oos.flush();
        return true;

要注意的是
(1) data是ListEntity接口的对象,该接口继承了Serializable接口,所以能够直接传參。
(2) key 在这里作为文件路径(缓存文件夹)。

3 最后,值得一提的是(尽管和Cache没有太大关系),解析完返回的数据后。刷新界面时,对返回数据的处理

 protected void executeOnLoadDataSuccess(List<T> data) {
  ...
        //对server返回来的数据和已有的数据进行对照。
        //假设同样。则将同样的item删掉。

最后看data集合的大小 //假设data最后仍然有item ,则更新ListView for (int i = 0; i < data.size(); i++) { if (compareTo(mAdapter.getData(), data.get(i))) { data.remove(i); i--; } } int adapterState = ListBaseAdapter.STATE_EMPTY_ITEM; if ((mAdapter.getCount() + data.size()) == 0) { adapterState = ListBaseAdapter.STATE_EMPTY_ITEM; } else if (data.size() == 0 || (data.size() < getPageSize() && mCurrentPage == 0)) { adapterState = ListBaseAdapter.STATE_NO_MORE; mAdapter.notifyDataSetChanged(); } else { adapterState = ListBaseAdapter.STATE_LOAD_MORE; } mAdapter.setState(adapterState); mAdapter.addData(data); // 推断等于1是由于最后有一项是listview的状态?? if (mAdapter.getCount() == 1) { if (needShowEmptyNoData()) { mErrorLayout.setErrorType(EmptyLayout.NODATA); } else { mAdapter.setState(ListBaseAdapter.STATE_EMPTY_ITEM); mAdapter.notifyDataSetChanged(); } } }

总结:
1 以上是自己初步从源代码中总结出来的一点关于缓存设计的认识和理解。肯定会有非常多不周或者不准确的地方,希望能够得到广大博友的指点。自己也会尽量抽出时间完好的。
2 源代码中有些地方,现阶段我也没有全然看懂。但仅仅要不影响大体上的把握,还是能够将自己的理解和整理的东西先分享出来。

作者:项昂之
时间:2015.7.15

posted on 2016-03-06 14:44  gcczhongduan  阅读(159)  评论(0编辑  收藏  举报