自定义带缓存效果的ImageView

数据的缓存是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;
	}
	
	//获得bitmap
	public 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;

		@Override
		protected Void doInBackground(Void... params) {
			bm = webImage.getBitmap();
			return null;
		}
		
		@Override
		protected void onPostExecute(Void result) {
			//如果拿不到图片,则给个系统的图片
			if (bm == null) {
				CustomImageView.this.setImageResource(R.drawable.ic_launcher);
			} else {
				CustomImageView.this.setImageBitmap(bm);
			}
		}

	}

}


打完收工!











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值