您的位置:首页 > 移动开发 > Android开发

android缓存设计

2015-09-11 18:15 316 查看
首先要提一下,本文中的缓存指的只是文本缓存。访问服务器使用http请求。

android里面使用缓存的好处:

1.节省流量

2.更快的响应,更流畅的体验。

3.减少http请求,降低服务器负担。

(如果一个应用启动到关闭共发起50次http请求,启用缓存后降低到了30次。我想缓存带来的效益要比你优化数据库表结构什么的优更加直接有效)

说到缓存,有几个必须提到的要点。

首先,每个缓存有应该有个id号,这样我们才能找到它或者删除它。

其次,既然是缓存,那必须有一个自己的生命周期或者说是有效期,这样缓存才能保持缓存的不断更新。

在android中应该用什么做缓存的id?什么做缓存?最简单直接的是用url做缓存id,用json做缓存内容。

比如请求一个商品id为1的商品信息的url是http://www.xxx.com?gid=1,获得的json数据格式{id:1,name:"一号商品",desc:"商品描述"}。这样下次在发起同样的http请求的时候,就不用从服务器获取数据了,直接根据url从本地找到对应的json即可。这里还有一点没说的就是缓存存储的问题。最简单的方式当然是存数据库,一张表两个字段。一个url,一个json。url设为主键,找缓存就是根据url找json了。
urljson
1http://www.xxx.com?gid=1{id:1,name:"一号商品",desc:"商品描述"}
2http://www.xxx.com?gid=2{id:2,name:"二号商品",desc:"商品描述"}
3http://www.xxx.com?gid=3{id:3,name:"三号商品",desc:"商品描述"}
4http://www.xxx.com?gid=4{id:4,name:"四号商品",desc:"商品描述"}
5http://www.xxx.com?gid=5{id:5,name:"五号商品",desc:"商品描述"}
为了让大家更好理解,一直没有说的太多。现在开始讲点复杂的。

刚才说到缓存还应该有个有效期。比如我设定的缓存的有效时间是2个小时。我可以用当前的时间减去上次缓存记录时的时间,看看这个时差是否大于两个小时即可。这样我们不得不修改一下缓存表
urljsonlastmodified
1http://www.xxx.com?gid=1{id:1,name:"一号商品",desc:"商品描述"}1388824029
2http://www.xxx.com?gid=2{id:2,name:"二号商品",desc:"商品描述"}1388824030
3http://www.xxx.com?gid=3{id:3,name:"三号商品",desc:"商品描述"}1388824031
4http://www.xxx.com?gid=4{id:4,name:"四号商品",desc:"商品描述"}1388824032
5http://www.xxx.com?gid=5{id:5,name:"五号商品",desc:"商品描述"}1388824033
表中的lastmodified就是缓存记录的时间,获取时间的方法System.currentTimeMillis();

现在就屡下逻辑:

首先是将要发起一个http请求(get请求),根据这个请求的url去数据库缓存表中查找有没有这条记录。如果没有,发起http请求。如果有,判读是否在有效期内,在有效期内直接使用,不在有效期,发起http请求。



自己对应缓存有效性的逻辑中认为:如果没有网络的情况下,即使缓存超过有效期也视为缓存有效。

除了利用数据库做缓存外还可以利用文件做缓存。

get请求的url作为文件名,请求的内容(如json)写入文件。这里要有些变通。以为文件名不能存在特殊字符所以可以把url进行MD5加密后的字符串作为文件名,写入文件的内容亦可以是json解析后的JavaBean再进行序列化。每个文件都有个最后修改时间,我们可以利用文件的这个属性来判断缓存的有效性。

转自:/article/1751468.html

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.baidu.manager.tool;

import android.util.Base64;
import com.baidu.manager.frame.Configure;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author Administrator
*/
public class HttpCacheUtil {

//目前是内存缓存
private static Map<String, HttpCacheResponse> cache = new ConcurrentHashMap<String, HttpCacheResponse>();

private static HttpCacheUtil instance;

private HttpCacheUtil() {
}

public static HttpCacheUtil getInstance() {
if (null == instance) {
instance = new HttpCacheUtil();
}
return instance;
}

/**
* 根据url从缓存中取数据
*/
public HttpCacheResponse getValue(String url, Map<String, String> params, String encoding,int methodtype) {
String cachekey=url;
StringBuffer sb=new StringBuffer(url);
for (Map.Entry<String, String> entry : params.entrySet()) {
String entrykey=entry.getKey();
String value=entry.getValue();
sb.append("&"+entrykey+"="+value);
}
String data=Base64.encodeToString(sb.toString().getBytes(), Base64.DEFAULT);
if(data!=null)
{
cachekey=data;
}
HttpCacheResponse value = cache.get(cachekey);
//首先是将要发起一个http请求(get请求),根据这个请求的url去数据库缓存表中查找有没有这条记录。如果没有,发起http请求。如果有,判读是否在有效期内,在有效期内直接使用,不在有效期,发起http请求。
if (null == value) {
//发起请求
value=doRequest(cachekey,url,params,encoding,methodtype);
//缓存起来
cache.put(cachekey, value);
return value;
} else {
if(value.isExpired())
{
System.out.println("缓存过期了");
//缓存过期了。
value=doRequest(cachekey,url,params,encoding,methodtype);
//缓存起来
cache.put(cachekey, value);
}else{
System.out.println("缓存没有过期了");
}
return value;
}
}

/**
* 清空缓存
*/
public void clearCache() {
cache.clear();
}

private HttpCacheResponse doRequest(String cachekey,String url, Map<String, String> params, String encoding, int methodtype) {

try {
String data=HttpService.getPOSTRequestResult(url, params, encoding);
long expiredTime=System.currentTimeMillis()+Configure.cacheTime*1000;//缓存一分钟。
HttpCacheResponse httpCacheResponse=new HttpCacheResponse(cachekey, encoding, expiredTime, true);
httpCacheResponse.setResponseBody(data);
httpCacheResponse.setResponseCode(200);
return httpCacheResponse;
} catch (Exception ex) {
Logger.getLogger(HttpCacheUtil.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}

//差个有效期自动销毁  java/android http数据缓存
public static void main(String[] args) throws InterruptedException {
String url = "http://www.baidu.com/";
for (int i = 0; i < 10; i++) {
long start = System.currentTimeMillis();
Map<String, String> params = new HashMap<String, String>();
params.put("module", "user");
params.put("action", "list");

Thread.sleep(8*1000);
HttpCacheResponse result = HttpCacheUtil.getInstance().getValue(url,params,"utf-8",0);
System.out.println(result.getResponseBody());
long end = System.currentTimeMillis();
System.out.println(end - start + " ms");
}

}

}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.baidu.manager.tool;

import java.util.HashMap;
import java.util.Map;

/**
*
* @author Administrator
*/
public class HttpCacheResponse {

private String url;
/**
* http response content *
*/
private String responseBody;
private Map<String, Object> responseHeaders;
/**
* expired time in milliseconds *
*/
private long expiredTime;
/**
* this is a client mark, whether this response is in client cache *
*/
private boolean isInCache;

private int responseCode = -1;

public HttpCacheResponse(String url, String responseBody, long expiredTime, boolean isInCache) {
this.url = url;
this.responseBody = responseBody;
this.expiredTime = expiredTime;
this.isInCache = isInCache;
responseHeaders = new HashMap<String, Object>();
}

public HttpCacheResponse(String url) {
this.url = url;
responseHeaders = new HashMap<String, Object>();
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getResponseBody() {
return responseBody;
}

public void setResponseBody(String responseBody) {
this.responseBody = responseBody;
}

public Map<String, Object> getResponseHeaders() {
return responseHeaders;
}

public void setResponseHeaders(Map<String, Object> responseHeaders) {
this.responseHeaders = responseHeaders;
}

public long getExpiredTime() {
return expiredTime;
}

public void setExpiredTime(long expiredTime) {
this.expiredTime = expiredTime;
}

public boolean isIsInCache() {
return isInCache;
}

public void setIsInCache(boolean isInCache) {
this.isInCache = isInCache;
}

public int getResponseCode() {
return responseCode;
}

public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}

/**
* whether this response has expired
*
* @return
*/
public boolean isExpired() {
return  System.currentTimeMillis() > expiredTime;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: