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>
这个案例比较简单,更加深入的讨论可以参看相关文献。很多时候,应用缓存机制还需要考虑一下几点:缓存的容量不是无限大的,需要给定一个可调整的值;缓存需要有相应的清理策略;缓存列表不能只放在内存里面,还需要利用数据库等进行长期的有效维护。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories