02/17
2014

Android网络缓存

主要介绍可同步或异步获取数据、可自动根据服务器的返回头判断是否需要缓存、可自动根据请求头信息判断是否读取缓存的网络缓存
本文分为四部分包括使用示例、功能介绍、原理介绍、疑问解答。

更多 Android 网络库开源项目可见:Android 网络库

 

适用:网络获取内容不大的应用,尤其是api接口数据,如新浪微博、twitter的timeline、微信公众账号发送的内容等等。

 

Demo APK 可以方便的查看效果,在各大应用商店搜索 trinea android 下载即可,如:Google Play

示例代码地址见HttpCacheDemo,效果图如下:

 

1、使用
(1)引入公共库
引入TrineaAndroidCommon@Github(欢迎star和fork^_^)作为你项目的library(如何拉取代码及添加公共库)。

 

(2)调用
仅需简单两步:

a. 定义缓存

private HttpCache httpCache = new HttpCache(context);

或获取全局唯一实例HttpCache

private HttpCache httpCache = CacheManager.getHttpCache(context);

 

 

b. 调用httpGet函数同步或异步获取网络数据

以httpGet函数异步获取数据为例,其他接口见第2部分介绍

httpCache.httpGet("http://www.trinea.cn/", new HttpCacheListener() {

	protected void onPreGet() {
		// do something like show progressBar before httpGet, runs on the UI thread 
	}

	protected void onPostGet(HttpResponse httpResponse, boolean isInCache) {
		// do something like show data after httpGet, runs on the UI thread 
		if (httpResponse != null) {
			// get data success
			setText(httpResponse.getResponseBody());
		} else {
			// get data fail
		}
	}
});

 

(3) 要求
缓存过期时间是根据服务器返回头中的cache-control和expires决定的,所以服务器需要设置这两个参数才能生效。具体可见第3部分原理介绍

 

2、功能介绍
(1) 几个相关类
HttpRequest 请求信息类,可设置超时时间、请求参数、UserAgent、请求属性等
HttpResponse 请求数据返回类,可获取接口内容、过期时间等。
HttpCacheListener 请求回调接口,onPreGet方法会在请求前执行,onPostGet方法会在请求结束后执行,两个方法都运行在UI线程

 

(2) 构造函数
目前的构造函数仅有一个,后面增加二级缓存可能会添加另外的构造函数
public HttpCache(Context context)

 

(3) 异步获取网络数据
public void httpGet(String url, HttpCacheListener listener)
根据url获取数据,获取前自动调用listener的onPreGet方法,获取后自动调用listener的onPostGet方法

 

public void httpGet(HttpRequest request, HttpCacheListener listener)
根据request获取数据,获取前自动调用listener的onPreGet方法,获取后自动调用listener的onPostGet方法

 

(4) 同步获取网络数据
public String httpGetString(String url)
根据url获取数据,网络错误返回null,否则返回数据为string

 

public HttpResponse httpGet(String url)
根据url获取数据,网络错误返回null,否则返回数据以HttpResponse.getResponseBody()获取

 

public HttpResponse httpGetString(HttpRequest httpRequest)
根据request获取数据,网络错误返回null,否则返回数据为string

 

public HttpResponse httpGet(HttpRequest request)
根据request获取数据,网络错误返回null,否则返回数据为string

 

(5) 其他
public boolean containsKey(String url) 判断某个url是否已经在缓存中并且有效

 

public void clear() 清空缓存

 

3、原理介绍
遵循Http/1.1 rfc2616规范,根据服务器Response Header中的Cache-Control字段的max-age确定缓存时间,如果不存在就取Response Header中的Expires做为缓存过期时间,如示例demo中的

http://www.trinea.cn/test-for-http-cache.html

用chrome查看截图如下:

 

4、疑问解答
(1) 缓存时间是多少或为什么我的url始终不缓存
缓存时间是根据服务器的返回时间决定的,详见上面第3部分原理介绍

 

(2) 如果某次请求不想使用缓存数据或返回数据不想被缓存怎么办
a. 某次请求不想使用缓存
在调用httpGet方法时设置入参HttpRequest,如下:
request.setRequestProperty(“cache-control”, “no-cache”);

 

b. 某次请求返回数据不想被缓存
在调用httpGet方法时设置入参HttpRequest,如下:
request.setRequestProperty(“cache-control”, “no-store”);

 

更多 Android 网络库开源项目可见:Android 网络库

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

47 thoughts on “Android网络缓存

  1. 博主,我的工程 里面是直接用的volley,我看了一下代码,volley已经实现了http头部定义的缓存。 没有仔细看。我感觉,直接用volley方便很多。不过我之后要实现一个自己定义的持久缓存,就是缓存时间比较长的,对于一些不容易修改的内容的缓存,比如缓存半年。 这种缓存,如果后台更新的话,后台返回的url和缓存的url不一样,这样就会直接加载后台。我个人觉得volley很不错。 希望博主可以更新一个这个库的博客。

    • httpPost确实没提供异步的方法,不过跟get一样,加上异步task就可以了。没用实体类做为参数,是考虑到一般参数也就用实体类中的个别字段,这样要作为共性抽取出来就不是很方便了。

  2. 还有,我看你的网络cache是只有一级缓存在db的对吧?eoe的代码里是用了两级的,一级是SoftReference的,二级是db的。不知道用二级缓存是不是有明显的好处?

    • 软引用是不会带来性能提升的,只是防止内存泄露。二级缓存我在设计,之所以还没写,一方面是因为对性能提升没那么明显,第二方面是因为api设计上我在考虑怎样更合适,最后我一直很忙,这个完全排不上优先级……

  3. 我在之前的开发里会遇到httpurlconnection对电信3g和联通3g的wap支持不好的情况,你的库有针对的处理么?我看源码好像没有。另外,google play store的源码是不是不公开的啊?

  4. 博主,问个与文章无关的问题啊。当需要在TextView显示多个信息拼接的结果时,拆分为多个TextView好不好呢。举例,有效期:从 1 月 到 2 月,是用尽量少的TextView显示拼接的结果好呢?还是用多个TextView显示好呢?

        • TextView多个信息拼接,可以在string.xml用,用代替符来连接。 比如一个TextView要显示 性名、年龄、身高,只需要定义一个string : 姓名:%1$s 年龄:%1$s 身高:%1$s 就行了。代码里用getString(int, args),传入要拼接的str就能得到一个连接好的string了。 不过这种方法只适合字体样式一样的情况。不过,还是看个人习惯

  5. 无意中看到你写的android的东西,感觉很好,我是一个新手,也看过不少视频和网上博文,但是总觉得基础差很多,能给我推荐几本新手的实用书吗。感觉你的眼光不会错,谢谢了大神!