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

Android的缓存机制——图片的缓存

2015-07-15 13:19 666 查看
缓存的目的是避免重复计算,特别是对消耗时间和资源的计算。Android中的缓存机制是利用本地存储实现的。


1.新下载数据的时候,将数据缓存到本地。

2.再次下载之前,先判断该资源是否已经被缓存,如果是,则优先使用本地资源,如果没有被缓存,则从网上下载资源,并进行缓存。

这里需要额外考虑两个因素:空间和时间。比如以缓存文本为主的应用,由于问恩本身占用极小的空间,其缓存大小可以根据用户的磁盘空间大小来确定;以缓存图片为主的应用,由于图片占用空间较大,更加需要用户参与指定空间大小。

3.对于时间限制,可以通过设定缓存的过期时间来实现,为下载到缓存的数据设定时间戳,在读取改缓存的时候,比较时间戳,超过时间限制的则需要更新改缓存。在清空应用缓存的时候也需要谨慎,在存储空间已满,用户注销的时候可以考虑清空改用户的整个缓存,而在普通升级应用的情况下并不需要清空整个缓存。

下面我们用AsyncTask方法,在后台下载图片,利用缓存机制显示。

public class PictureShowActivity extends Activity{

//新建URL
URL url;
//获取SD卡根目录
String sdcardPATH = Environment.getExternalStorageDirectory() + "/";
//设置缓存的目录
String cachePath = sdcardPATH + "pictureCache";
Button showPicture;
ImageView pictureView;
EditText urlText;
HashMap<String, String> cacheMap = new HashMap<String, String>();
File file;
String urlString;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//设置布局文件
setContentView(R.layout.activity_picture_show);
//绑定控件
pictureView = (ImageView)findViewById(R.id.pictureView);
urlText = (EditText)findViewById(R.id.urlText);
showPicture = (Button)findViewById(R.id.showPicture);
//添加按钮监听
showPicture.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//获取图片地址
urlString = urlText.getText().toString();
//输入检测
if(urlString != null && urlString.length() >0){
//检测图片地址
urlString = (urlString.startsWith("http://")) ? urlString : "http://" + urlString;
if(cacheMap != null && cacheMap.containsKey(urlString)){
//获取保存的地址
String cacheFile = cacheMap.get(urlString).toString();
//验证该地址的文档是否存在
if(checkFileExists(cacheFile)){
//存在则显示缓存中的内容
Drawable d = Drawable.createFromPath(cacheFile);
pictureView.setImageDrawable(d);
}else{
//不存在则显示缓存中的内容
downFile(urlString);
}
}else{
//存在则直接显示
downFile(urlString);
}
}
}
});
}
//下载文件
public void downFile(String url){
//调用异步下载方法
new DownloadFileTask().execute(url);
}

//判断文件是否已经存在
public boolean checkFileExists(String filepath){
//新建文件对象
File file = new File(filepath);
return file.exists();
}

//以异步方式下载文件
private class DownloadFileTask extends AsyncTask<String, Integer, Integer>{
//后台下载
@Override
protected Integer doInBackground(String... sUrl) {
// TODO Auto-generated method stub
try{
//获取URL地址
String urlString = sUrl[0];
//实例化url对象
url = new URL(urlString);
//打开连接
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
//获取内容
InputStream istream = connection.getInputStream();
//获取文件名称
String filename = urlString.substring(urlString.lastIndexOf("/") + 1);
//实例化新的文件目录
File dir = new File(cachePath);
//判断文件目录是否存在
if(!dir.exists()){
//创建目录
dir.mkdir();
}
//实例化新的文件
file = new File(cachePath + filename);
//创建文件
file.createNewFile();
//读取信息到文件中
OutputStream output = new FileOutputStream(file);
byte[] buffer = new byte[1024 * 4];
while(istream.read(buffer) != -1){
output.write(buffer);
}
//写入文件
output.flush();
output.close();
istream.close();
}catch(Exception ex){
ex.printStackTrace();
return -1;
}
return 1;
}

@Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
//如果没有异常
if(result > 0){
//保存到缓存维护键值对
cacheMap.put(urlString,  file.getPath());
Drawable d = Drawable.createFromPath(file.getPath());
pictureView.setBackgroundDrawable(d);
}
}
}
}


布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="URL: "/>

<EditText
android:id="@+id/urlText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="http://www.adnroid.com/images/logo.png" />
</LinearLayout>

<Button
android:id="@+id/showPicture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ShowPicture"/>

<ImageView
android:id="@+id/pictureView"
android:layout_width="match_parent"
android:layout_height="50dp"/>

<!--  <ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher"/> -->

</LinearLayout>
需要加入两个权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>


这个案例比较简单,更加深入的讨论可以参看相关文献。很多时候,应用缓存机制还需要考虑一下几点:缓存的容量不是无限大的,需要给定一个可调整的值;缓存需要有相应的清理策略;缓存列表不能只放在内存里面,还需要利用数据库等进行长期的有效维护。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息