在上一篇日誌《Android Bitmap OOM系列(1):GridView》中,我們已經成功的讓GridView跑起來了,但是這是最最原始的實現方式之一,它的效率也是非常之低(我們的圖片都是來自於項目中,而且都是微小圖片,所以感受不到),一旦圖片的分辨率比較大,而且圖片數量多的話,應用很容易因為內存爆掉而導致FC(Force close)。這是因為我們在getView方法中始終是new一個新的View出來,如此一來,一旦有100張圖,我們就要new 100次,同時當我們滾動GridView的時候,即使是顯示在界面上過的View也會重新new一次。而同時Dalvik虛擬機又未能及時回收已不用的內存,當到達極限時,內存也就理所當然地爆掉了。
在寫getView這個方法中的代碼時,我們已經發現,getView有一個參數View(參數名為convertView),在android的ListView、Gridview中,convertView是一個很有用,而且很酷的參數。根據官方文檔的解釋,它是用來在可能的情況下重用舊的視圖的。在使用之前,我們應該先檢查這個view不是空的而且是一個適當的類型。所以呢,我們現在就來把getView給改寫一下。改寫後的代碼如下:
View view = null ; if ( convertView == null ) { view = mInflater . inflate ( R . layout . gridview , null ); ImageView imageView = ( ImageView ) convertView . findViewById ( R . id . image ); imageView . setImageBitmap ( bitmapList . get ( position )); } else { view = convertView } return view ;
首先我們判斷convertView是否為空,當為空時,就按照原來的邏輯去xml中尋找控件並實例化出來,然後把BItmap設置進ImageView,如果不為空,就直接將convertView賦給view。
這次的改寫就這麼簡單,當然這個還是簡單的形式,因為我們現在只有一個ImageView而已,如果在項目中我們GridView的每一個View都是由多個控件組成(比如一個ImageView和一個TextView),那麼我們還需要建一個holder來儲存。首先我們需要建一個holder類(我比較喜歡直接寫在adapter裡作為內部類使用),它只包含2個成員變量
public class Holder { public TextView text ; public ImageView image ; }
然後在getView中使用這個holder,首先我們先實例化Holder為null,然後如同上面那樣判斷convertView是否為空,並進行相應的實例化操作。所不同的是,這裡我們不再需要new 一個ImageView出來了,我們直接把xml中讀出來的ImageView賦值給Holder的成員變量image,TextView也一樣。然後分別給他們設ImageBitamp和Text,之後把Holder設置到convertView裡面去。當convertView不為空的時候,則從convertView中取出相應Holder的視圖出來。
View view = null ; Holder holder = null ; if ( convertView == null ) { view = mInflater . inflate ( R . layout . gridview , null ); holder = new Holder (); holder . image = ( ImageView ) convertView . findViewById ( R . id . image ); holder . image . setImageBitmap ( bitmapList . get ( position )); convertVIew . setTag ( holder ); } else { view = convertView . getTag (); } return view ;
原創文章,轉載請註明:轉載自網憩閣
Google的教學:
static class ViewHolder {
TextView text;
ImageView icon;
}
------------------------------------------------
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text,
parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
-----------------------------------------------------------
public class MyBaseAdapter extends BaseAdapter {
private Context myContext;
MyBaseAdapter(Context c) {
myContext = c;
}
public class ViewHolder {
TextView text;
ImageView icon;
}
@Override
public int getCount() {
return MyAppList.size();
}
@Override
public Object getItem(int position) {
return MyAppList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/*View MyView = convertView;
if (convertView == null) {
MyView = new View(myContext);
MyView.setLayoutParams(new GridView.LayoutParams(85, 85));
// MyView.setScaleType(View.ScaleType.CENTER_CROP);
MyView.setPadding(8, 8, 8, 8);
} else {
MyView = (View) convertView;
}
LayoutInflater li = getLayoutInflater();
MyView = li.inflate(R.layout.grid_item, null);
// Add The Text!!!
TextView tv = (TextView) MyView.findViewById(R.id.tv);
tv.setText(MyAppList.get(position));
// Add The Image!!!
ImageView iv = (ImageView) MyView.findViewById(R.id.imageView1);
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
iv.setImageBitmap(getThumbnail("icon " + MyAppList.get(position)
+ ".png", getBaseContext()));
return MyView;*/
ViewHolder holder;
LayoutInflater li = getLayoutInflater();
if (convertView == null) {
convertView = li.inflate(R.layout.grid_item,
parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.tv);
holder.icon = (ImageView) convertView.findViewById(R.id.imageView1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(MyAppList.get(position));
holder.icon.setImageBitmap(getThumbnail("icon " + MyAppList.get(position)
+ ".png", getBaseContext()));
return convertView;
}
}
"不再" Force close的 gridview
忽略一些東西, 能換來一些東西
沒有留言:
張貼留言