android 加載圖片防止內存溢出

圖片資源:




private int fore[];
private int back[];
fore = new int[]{R.drawable.a0, R.drawable.a1, R.drawable.a2,
				R.drawable.a3, R.drawable.a4, R.drawable.a5,
				R.drawable.a6, R.drawable.a7, R.drawable.a8,
				R.drawable.a9, R.drawable.a910, R.drawable.a911,
				R.drawable.a912, R.drawable.a913, R.drawable.a914};
back = new int[]{R.drawable.b0, R.drawable.b1, R.drawable.b2,
				R.drawable.b3, R.drawable.b4, R.drawable.b5,
				R.drawable.b6, R.drawable.b7, R.drawable.b8,
				R.drawable.b9, R.drawable.b910, R.drawable.b911,
				R.drawable.b912, R.drawable.b913, R.drawable.b914};
//用戶保存加載的圖片
private List bitmapResource = new ArrayList();

GridView grid;//聲明 圖片顯示 類似九宮格 的 控件

Handler handler; //聲明 Handler 用來傳遞消息



計算方法:


int width = (int) (getWindowManager().getDefaultDisplay().getWidth()/density);//取得屏幕的寬度 
ImageResource ir = new ImageResource();
//使用getPicture()方法 加載圖片
 public void getPicture(){
    	new AsyncTask() {//	進度條類 異步處理
			@Override
			protected Object doInBackground(Object... params) {//後臺執行,比較耗時的操作都可以放在這裡。
				publishProgress();//來更新任務的進度。
				loadingBitmap(getResources(), width, 3);//對圖片進行縮放的方法 ,這裡3為要顯示的列數
				return null;
			}


			@Override
			protected void onPostExecute(Object result) {//在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後臺的計算結果將通過該方法傳遞到UI thread. 
				handler.removeCallbacks(update);//removeCallbacks方法是刪除指定的Runnable對象,使線程對象停止運行。
				message.setVisibility(View.GONE);//message設置為不可見
				author_message.setVisibility(View.GONE);//author_message設置為不可見
				grid.setVisibility(View.VISIBLE);//grid設置為可見
				grid.setNumColumns(3);//設置GridView的列數
				grid.setHorizontalSpacing(20);//兩列之間的間距
				grid.setVerticalSpacing(40);//兩行之間的間距
				grid.setAdapter(adapter);//使用適配器
				grid.setOnItemClickListener(new OnItemClickListener() {//GridView 的監聽器
					
					public void onItemClick(AdapterView arg0, View arg1,
							int position, long arg3) {
						Intent intent = new Intent();//實例化Intent
						intent.setClass(MenuActivity.this, ShowActivity.class);//設置跳轉路徑
						Bundle bundle = new Bundle();//實例化Bundle類 傳值
						bundle.putInt("num",position);//傳 列表的 位置值 到ShowActivity
						intent.putExtras(bundle);//intent發送Bundle
						MenuActivity.this.startActivity(intent);//開始跳轉
					}
				});
				adapter.notifyDataSetChanged();//在adapter的數據發生變化以後通知UI主線程根據新的數據重新畫圖。
				super.onPostExecute(result);
			}


			
			protected void onProgressUpdate(Object... values) {//在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況
				
				handler = new Handler();//實例化handler
				//顯示加載進度
				handler.post(update);//根據線程來更新進度
				
				super.onProgressUpdate(values);
			}
		}.execute();//執行 異步操作
    }

public void loadingBitmap(Resources resources, int width, int num){


		BitmapFactory.Options opts = new BitmapFactory.Options();//BitmapFactory.Options這個類
		//僅返回圖片的 寬高  這樣就不會占用太多的內存,也就不會那麼頻繁的發生OOM瞭。
		opts.inJustDecodeBounds = true;//該值設為true那麼將不返回實際的bitmap對象,不給其分配內存空間但是可以得到一些解碼邊界信息即圖片大小等信息。
		Bitmap temp = BitmapFactory.decodeResource(resources, fore[0], opts);//加載圖片 縮放 從fore【】中第一位開始
		int radio = (int) Math.ceil(opts.outWidth / (width*1.0 / num - 30));//向上取整 結果是7,得到縮放比例radio
		//Math.ceil(12.2)//返回13
		//Math.ceil(12.7)//返回13
		//Math.ceil(12.0)// 返回12
		opts.inSampleSize = radio;//屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一
		if(null != temp){
			temp.recycle();//回收
		}
		System.out.println(radio);
		
		opts.inJustDecodeBounds = false;//inJustDecodeBounds設為false,就可以根據已經得到的縮放比例得到自己想要的圖片縮放圖瞭。
		
		for(int i = 0; i < fore.length; i++){
			Bitmap bitmap = BitmapFactory.decodeResource(resources, fore[i], opts);//載入圖片
			bitmapResource.add(bitmap);//循環添加到集合中
		}
	}

使用適配器:

 BaseAdapter adapter = new BaseAdapter() {
		
		
		public View getView(int position, View convertView, ViewGroup parent) {
			ImageView iv = new ImageView(MenuActivity.this);//顯示任意圖像
			iv.setMaxWidth(width / 3 - 30);//設置寬度
			iv.setAdjustViewBounds(true);//是否保持寬高比
			iv.setImageBitmap(ir.getIconBitmap(position));//設置圖片 使用ImageResource類中集合當中的圖片
			return iv;
		}
		
		@Override
		public long getItemId(int position) {//得到ID
			return position;
		}
		
		@Override
		public Object getItem(int arg0) {//得到位置
			return arg0;
		}
		
		@Override
		public int getCount() {//得到大小
			return ir.size();
		}
	};
Runnable update = new Runnable() {//實例化線程
		@Override
		public void run() {
			int progress = ir.getProgress();//得到文件的總大小
			if(null != message){
				message.setText("數據加載中("+progress+"%),請稍等……\n\n");//如果message不是空,就讓顯示文本
			}
			if(100 == progress){
				handler.removeCallbacks(update);//等於100 也即是說 加載完畢 就停止線程,也就是關閉此定時器
			} else {
				handler.postDelayed(update, 200);//使用PostDelayed方法,兩秒後調用此Runnable對象,實際上也就實現瞭一個0.2s的一個定時器
			}
		}
	};



發佈留言