自定义带缓存效果的ImageView

来源:互联网 发布:程序员在哪里写博客 编辑:程序博客网 时间:2024/05/20 23:36

数据的缓存是android中常用的机制,虽然现在有很多框架已经实现了缓存+http请求等等一系列的操作,但是还是缕缕其中的代码过程吧,其实过程很简单,就是在加载数据时判断是否被缓存,没有就进行缓冲(也就是存在本地文件中),有了就直接拿存的数据来用就行了,而ImageView是常用控件,如果用了缓存思想应该会方便很多的,贴出之前做的demo的代码



基本思想

// 1. 尝试从内存缓存(当前控件中自定义的属性,表示图片数据)中加载图片
// 2. 尝试从本地文件中读取图片数据,无论是否读取到,最终,都将把图片数据写入到内存的缓存(为属性赋值)
// 3. 尝试从网络中下载图片,下载完成依然会执行之前的操作:把图片数据写入到内存的缓存(为属性赋值)
// Ps. 开启子线程完成加载,并在主线程中更新UI



这里定义一个WebImage类,用于网络请求+本地缓存操作

<span style="font-size:18px;">package cn.com.tarena.music_online.view;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.HashMap;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import android.os.Environment;public class WebImage {private String url;private Options opts;private Map<String, Bitmap> cache = new HashMap<String, Bitmap>();public void setUrl(String url) {this.url = url;}public WebImage(String url) {this.url = url;}public WebImage(String url, Options opts) {this.url = url;this.opts = opts;}private void setCacheBitmap(Bitmap bitmap) {cache.put(getLocalFileName(), bitmap);}private Bitmap getCacheBitmap() {return cache.get(getLocalFileName());}//创建一个缓存文件private File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"custom_image_cache");//设置文件名字,将敏感字符全部替换掉private String getLocalFileName() {String fileName = url;fileName = fileName.replace(":", "+");fileName = fileName.replace("/", "+");fileName = fileName.replace("\\", "+");fileName = fileName.replace("?", "+");fileName = fileName.replace("|", "+");fileName = fileName.replace("*", "+");fileName = fileName.replace("\"", "+");fileName = fileName.replace("\'", "+");fileName = fileName.replace("!", "+");return fileName;}//获得bitmappublic Bitmap getBitmap() {Bitmap bm = getCacheBitmap();if (bm == null) {bm = getBitmapFromLocalFile();//如果本地文件为null,则调用downloadImageFromWeb()请求网络资源if (bm == null) {downloadImageFromWeb();bm = getBitmapFromLocalFile();}}return getCacheBitmap();}//获得本地bitmap资源private Bitmap getBitmapFromLocalFile() {if (!dir.exists()) {return null;}Bitmap bm = null;File localFile = new File(dir, getLocalFileName());if (!localFile.exists()) {return null;}bm = BitmapFactory.decodeFile(localFile.getAbsolutePath(), opts);setCacheBitmap(bm);return bm;}//网络请求数据并存储在本地private void downloadImageFromWeb() {HttpClient client = null;HttpGet request = null;HttpResponse response = null;HttpEntity entity = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;File localFile = null;try {client = new DefaultHttpClient();request = new HttpGet(url);response = client.execute(request);if (200 == response.getStatusLine().getStatusCode()) {entity = response.getEntity();localFile = new File(dir, getLocalFileName());if (!dir.exists()) {dir.mkdirs();}bis = new BufferedInputStream(entity.getContent());bos = new BufferedOutputStream(new FileOutputStream(localFile));byte[] buffer = new byte[1024];int len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.flush();}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (bos != null) {bos.close();bos = null;}} catch (IOException e) {e.printStackTrace();}}}}</span>




然后我们定义一个CustomImageView来继承ImageView

package cn.com.tarena.music_online.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory.Options;import android.os.AsyncTask;import android.util.AttributeSet;import android.widget.ImageView;import cn.com.tarena.music_online.R;public class CustomImageView extends ImageView {private WebImage webImage;// 带1个参数的构造方法,适用于在JAVA程序中使用new ???()的语法,创建控件的对象public CustomImageView(Context context) {super(context);}// 带2~3个参数的构造方法,适用于在res\layout下设计布局,添加各项属性,最后,通过LayoutInflater加载到程序中public CustomImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// TODO 自定义需要在构造方法中完成的代码}/** * 显示来自网络的图片 *  * <p> * 本功能会自动缓存图片的数据分别到本地文件与内存,当显示图片时,将根据内存 -> 本地文件的顺序尝试加载已缓存的图片数据。 * </p> *  * @param url *            网络上的图片的完整路径,例如 http://www.baidu.com/logo.png */public void setImageUrl(String url) {this.setImageUrl(url, null);}/** * 显示来自网络的图片 *  * <p> * 本功能会自动缓存图片的数据分别到本地文件与内存,当显示图片时,将根据内存 -> 本地文件的顺序尝试加载已缓存的图片数据。 * </p> *  * @param url *            网络上的图片的完整路径,例如 http://www.baidu.com/logo.png * @param otps *            当BitmapFactory需要decode文件时的参数,例如将图片压缩等等 */public void setImageUrl(String url, Options opts) {if (webImage == null) {webImage = new WebImage(url, opts);} else {webImage.setUrl(url);}new LoadWebImageTask().execute();}//异步操作来执行WebImage操作private class LoadWebImageTask extends AsyncTask<Void, Void, Void> {private Bitmap bm;@Overrideprotected Void doInBackground(Void... params) {bm = webImage.getBitmap();return null;}@Overrideprotected void onPostExecute(Void result) {//如果拿不到图片,则给个系统的图片if (bm == null) {CustomImageView.this.setImageResource(R.drawable.ic_launcher);} else {CustomImageView.this.setImageBitmap(bm);}}}}


打完收工!











0 0
原创粉丝点击