Android系统为我们提供了一个封装好的类,该类能够在去完成后台的操作的同时去更新UI,大家都知道,一般执行后台耗时的操作都会放在一个子线程中执行,更新UI的操作则需在主线程或UI线程中执行(UI线程实际上是在主线程中实现的),所以我们不得不通过Android的消息处理机制在合适的时机去通知主线程执行UI的操作,所以就出现了这个封装好了的AsyncTask类来帮助我们方便的完成上述的操作。
大概意思是:AsyncTask类能够让我们在使用UI线程的时候更加方便和容易,这个类能够让我们不直接操作线程和消息处理器Handler的前提下去完成后台的操作,并将执行的结果返回到UI线程中去完成界面的更新,所以很明显,他内部已经为咱们封装好了,上代码:
package com.example.threelevelcache;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.util.DisplayMetrics;
import android.widget.ImageView;
import com.example.threelevelcache.utils.Md5Utils;
public class BitmapUtils {
private final int LOAD_PICTURE_SUCCESS = 0 ;
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8 );
private File dir;
private Context context ;
public BitmapUtils(Context context) {
this .context = context ;
dir = new File("mnt/sdcard/bitmapFile" );
if (!dir.exists()) {
dir.mkdirs();
}
}
/**
* android 2.3之后,supportv4包中提供了一个缓存的静态类LruCache
*/
private LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(
maxSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024 ;
};
};
/**
* 执行异步任务的、继承了AsyncTask的类
*
* @author Administrator
*
*/
private class MyAsyncTask extends
AsyncTask<ImageViewUrl, Integer, BitmapImageBounding> {
@Override
protected void onPreExecute() {
super .onPreExecute();
}
@Override
protected BitmapImageBounding doInBackground(ImageViewUrl... params) {
String url = params[0 ].url;
ImageView iv = params[0 ].iv;
Bitmap bitmap = null ;
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(
HttpConnectionParams.CONNECTION_TIMEOUT, 3000 );
HttpGet httpGet = new HttpGet(url);
HttpResponse response = client.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200 ) {
InputStream is = response.getEntity().getContent();
bitmap = BitmapFactory.decodeStream(is);
lruCache.put(url, bitmap);
File bitmapFile = new File(dir, getFileName(url));
FileOutputStream fos = new FileOutputStream(bitmapFile);
bitmap.compress(CompressFormat.JPEG, 100 , fos);
}
} catch (Exception e) {
e.printStackTrace();
}
return new BitmapImageBounding(iv, bitmap);
}
@Override
protected void onPostExecute(BitmapImageBounding result) {
super .onPostExecute(result);
result.iv.setImageBitmap(result.bitmap);
}
}
/**
* 创建一个类用于关联ImageView和在该ImageView中显示的图片的url
*
* @author Administrator
*
*/
private class ImageViewUrl {
private ImageView iv;
private String url;
public ImageViewUrl(ImageView iv, String url) {
super ();
this .iv = iv;
this .url = url;
}
}
/**
* 将图片显示到ImageView中的方法
*
* @param iv
* 界面中的某个ImageView对象
* @param url
* 服务器某张图片的路径
*/
public void display(ImageView iv, String url) {
Bitmap bitmap = null ;
bitmap = getPictureFromCache(url);
if (bitmap != null ) {
iv.setImageBitmap(bitmap);
return ;
}
bitmap = getPictureFromSdcard(url);
if (bitmap != null ) {
iv.setImageBitmap(bitmap);
return ;
}
}
/**
* 1.从缓存加载图片
*
* @param url
* @return
*/
public Bitmap getPictureFromCache(String url) {
System.out.println("当前正在从内存缓存中获取图片" );
Bitmap bitmap = null ;
if (lruCache != null ) {
bitmap = lruCache.get(url);
}
return bitmap;
}
/**
* 2.从sd卡加载图片
*
* @param url
* @return
*/
public Bitmap getPictureFromSdcard(String url) {
System.out.println("当前正在从sd卡中获取图片" );
Bitmap bitmap = null ;
File bitmapFile = new File(dir, getFileName(url));
bitmap = decodeFile(bitmapFile.getAbsolutePath());
if (bitmap != null ) {
lruCache.put(url, bitmap);
}
return bitmap;
}
/**
* 解决从本地SDcard加载图片时可能导致OOM的问题
* 解决方案: 先加载图片的宽高,并获取到手机屏幕的宽高,对图片的宽高进行缩放处理
*
*/
private Bitmap decodeFile(String absolutePath) {
Options opts = new Options();
opts.inJustDecodeBounds = true ;
opts.inInputShareable = true ;
opts.inPurgeable = true ;
BitmapFactory.decodeFile(absolutePath, opts);
int sampleSize = calculateSampleSize(opts);
opts.inSampleSize = sampleSize ;
opts.inJustDecodeBounds = false ;
Bitmap bitmap = BitmapFactory.decodeFile(absolutePath, opts);
return bitmap ;
}
/**
* 如果图片的大小大于屏幕的大小,则获取图片缩放的比例
* @param opts
* @return
*/
private int calculateSampleSize(Options opts) {
int sampleSize = 1 ;
int bitmapWidth = opts.outWidth ;
int bitmapHeight = opts.outHeight ;
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
if (bitmapWidth > screenWidth || bitmapHeight > screenHeight){
int scaleWidth = bitmapWidth / screenWidth ;
int scaleHeight = bitmapHeight / screenHeight ;
sampleSize = scaleWidth > scaleHeight ? scaleWidth : scaleWidth ;
}
return sampleSize ;
}
/**
* 3.从网络加载图片
*
* @param iv
* @param url
*/
public void getPictureFromInternet(ImageView iv, String url) {
System.out.println("当前正在从网络中获取图片" );
new MyAsyncTask().execute(new ImageViewUrl(iv, url));
}
/**
* 创建一个类,用于绑定ImageView和在该ImageView上要显示的Bitmap对象
*
* @author Administrator
*
*/
private class BitmapImageBounding {
ImageView iv;
Bitmap bitmap;
public BitmapImageBounding(ImageView iv, Bitmap bitmap) {
super ();
this .iv = iv;
this .bitmap = bitmap;
}
}
/**
* 将url加密,并将加密后的字符串作为sd卡上保存该图片的文件夹的名称
*
* @param url
* @return
*/
public String getFileName(String url) {
return Md5Utils.encode(url);
}
}