圖片相關:bigmap工具類,實現壓縮、異步、併發、緩存

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





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章