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);
}
}