1.图片的压缩(图片太大可能会导致内存溢出)
2.图片的异步加载(耗时操作放在工作线程)
3.图片的并发异步加载(实现每个item中imageview对应一个异步任务并绑定一起)
4.图片的缓存问题
bigmap工具类:
public class BitmapUtils {
/**
* 计算压缩比例
*
* @param options
* 封装图片的实际的高度,宽度
* @param reqWidth
* 需要的宽度
* @param reqHeight
* 需求的高度
*/
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// read height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
// 通过此变量记录压缩比例(1表示不压缩)
int inSampleSize = 1;
// 计算压缩比例(假如图片的实际高度,宽度大于我们需要的宽度,高度则要计算压缩比例)
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
/** 压缩图片 */
public static Bitmap decodeSampledBitmapFromResource(String path, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true
// to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//此值为true表示只读图片边界信息
// read dimension (height,width)
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
}
ImageLoaderUtils工具类
实现图片压缩、异步、并发、缓存
public class ImageLoaderUtils {
private static LruCache<String, Bitmap> lruCache;
/**@param size 为缓存空间大小*/
public static void buildMemoryLruCache(int maxSize){
lruCache=new LruCache<String, Bitmap>(maxSize){
//此方法要返回每个缓存对象的大小
@Override
protected int sizeOf(String key, Bitmap value) {
// TODO Auto-generated method stub
return value.getByteCount();
}
};
}
/**将数据放到缓存中*/
public static void putMemoryLruCache(String key,Bitmap bitMap){
if(lruCache!=null){
lruCache.put(key,bitMap);
Log.i("TAG", "putMemoryLruCache");
}
}
/**从缓存中取数据*/
public static Bitmap getBitmapFromMemoryLruCache(String key){
if(lruCache!=null){
return lruCache.get(key);
}
return null;
}
public static void loadBitmapAsync(Context context,ImageView imageView,String path,int reqWidth,int reqHeight){
//1.判定内存时候有数据,内存有数据则直接显示?
Bitmap bitMap=getBitmapFromMemoryLruCache(path);
if(bitMap!=null){
imageView.setImageBitmap(bitMap);
return;
}
//2.内存没有则启异步任务加载数据,何时启动新的异步任务?
//a)imageview上没有绑定的异步任务
//b)imageView上有异步任务,但此异步任务正在加载的数据不是我们需要的数据
if(cancelBitmapWorkerTask(path,imageView)){
//构建异步任务
BitmapWorkerTask task=
new BitmapWorkerTask(imageView);
//构建一个AsyncDrawable对象,并绑定异步任务
Bitmap defaultBitmap=
BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_launcher);
AsyncDrawable drawable=
new AsyncDrawable(context,
defaultBitmap,//默认图片
task);
//imageview绑定drawable对象
imageView.setImageDrawable(drawable);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,path,reqWidth,reqHeight);
}
}
/**用于检测是否要创建新的异步对象*/
static boolean cancelBitmapWorkerTask(String reqPath,ImageView imageView){
//1.检测imageview上有没有绑定的异步任务
BitmapWorkerTask task=
getBitmapWorkerTask(imageView);
//2.检测异步中加载的数据是否是我们需要的数据
if(task!=null){
if(!task.loadingPath.equals(reqPath)){
task.cancel(true);//退出原有异步任务
return true;//开启新的异步任务
}else{
return false;//不需要重新开启异步任务
}
}
return true;
}
/**检测imageview上有没有绑定的异步任务*/
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView){
Drawable drawable=imageView.getDrawable();
if(drawable instanceof AsyncDrawable){
AsyncDrawable aDrawable=
(AsyncDrawable)drawable;
return aDrawable.getBitmapWorkerTask();
}
return null;
}
static class BitmapWorkerTask extends AsyncTask<Object, Integer, Bitmap> {
private WeakReference<ImageView> weakReference;
public BitmapWorkerTask(ImageView imageView) {
this.weakReference = new WeakReference<ImageView>(imageView);
}
private String loadingPath;
@Override
protected Bitmap doInBackground(Object... params) {
try{Thread.sleep(100);}catch(Exception e){};
loadingPath=(String)params[0];
//加载Bitmap对象
Bitmap bitMap=BitmapUtils.
decodeSampledBitmapFromResource(
loadingPath,
(Integer)params[1],
(Integer)params[2]);
//缓存bitmap对象
putMemoryLruCache(loadingPath, bitMap);
return bitMap;
}
@Override
protected void onPostExecute(Bitmap result) {
if(isCancelled())return;
if (weakReference != null && result != null) {
final ImageView imageView = weakReference.get();
BitmapWorkerTask task=getBitmapWorkerTask(imageView);
if (task==this&&imageView != null) {
imageView.setImageBitmap(result);
}
}
}
}
/**构建此类的目的是希望此对象与一个异步任务对象绑定在一起,
* 然后通过此对象的异步任务加载图片*/
static class AsyncDrawable extends BitmapDrawable {
private WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Context context,Bitmap bitMap,BitmapWorkerTask task) {
super(context.getResources(), bitMap);
this.bitmapWorkerTaskReference =new WeakReference<ImageLoaderUtils.BitmapWorkerTask>(task);
}
/*public void setBitmapWorkerTaskReference(BitmapWorkerTask task) {
this.bitmapWorkerTaskReference =new WeakReference<ImageLoaderUtils.BitmapWorkerTask>(task);
}*/
/**通过此方法获得一个BitmapWorkerTask*/
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
}
main:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建一个缓存LruCache对象
ActivityManager aManager=(ActivityManager)
getSystemService(Context.ACTIVITY_SERVICE);
int memorySize=aManager.getMemoryClass();
Log.i("TAG", "memorySize="+memorySize);
int lruCacheSize=memorySize*1024*1024/8;
ImageLoaderUtils.buildMemoryLruCache(lruCacheSize);
//初始化数据
AnimalProvider aProvider=new AnimalProvider();
//初始化listview
ListView lsv=(ListView) findViewById(R.id.lsvId);
AnimalAdapter adapter=new AnimalAdapter(this,
R.layout.list_item_02,aProvider.getAnimals());
lsv.setAdapter(adapter);
}
}