[英]Android Listview GC_FOR_ALLOC freed: DDMS android.graphics.Bitmap
我在android中使用listview遇到麻煩。 當我開始向下滾動列表時,它非常慢,並且看到GC被調用。 當我排在列表的底部時,一切都會順利進行。 我認為這時我的ViewHolder就可以了。
但是我找不到調用GC的源。 我搜索了導致:
DDMS 436816 byte[] 1 android.graphics.Bitmap nativeCreate
我無法解釋那條線。 我的ArrayAdapter
及其getView
方法如下所示:
public class DiagnoseAdapter extends ArrayAdapter<Visualizer> {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = TYPE_DEFAULT;
final Visualizer item = getItem(position);
switch(item.getType()){
case TYPE_DEFAULT:
convertView = DefaultTextView.getView(position, convertView, mlayoutInflater, item, parent);
break;
// more cases/types
}
return convertView;
}
}
它正在調用以下類的DefaultTextView
getView
方法
public class DefaultTextView{
public static View getView(int position, View convertView, LayoutInflater layoutInflater, Visualizer item, ViewGroup parent){
ViewHolder holder;
if (convertView == null || item.getReleatedObject() == null || convertView.getTag()!=TAG_DEFAULT) {
convertView = layoutInflater.inflate(R.layout.diagnose_item, null);
holder = new ViewHolder();
holder.value = (TextView) convertView.findViewById(R.id.diagnose_function_value);
holder.name = (TextView) convertView.findViewById(R.id.diagnose_function_setname);
holder.mLinLayout = (LinearLayout) convertView.findViewById(R.id.default_linlayout);
convertView.setTag(TAG_DEFAULT);
convertView.setTag(R.layout.diagnose_item,holder);
item.setReleatedObject(convertView);
} else {
holder = (ViewHolder) convertView.getTag(R.layout.diagnose_item);
}
holder.value.setText(item.toString());
holder.name.setText(item.getToolTip());
holder.mLinLayout.removeAllViews();
if (item.getUpdateFlag(4)) {
if (holder.back == null){
holder.back = new ImageView(convertView.getContext());
holder.back.setScaleType(ScaleType.FIT_CENTER);
holder.back.setAdjustViewBounds(true);
holder.back.setImageBitmap(bm1);
}
holder.mLinLayout.addView(holder.back);
}
if (item.getUpdateFlag(1)) {
if (holder.update == null){
holder.update = new ImageView(convertView.getContext());
holder.update.setScaleType(ScaleType.FIT_CENTER);
holder.update.setAdjustViewBounds(true);
holder.update.setImageBitmap(bm2);
}
holder.mLinLayout.addView(holder.update);
}
if (item.getUpdateFlag(2)) {
if (holder.timer == null){
holder.timer = new ImageView(convertView.getContext());
holder.timer.setScaleType(ScaleType.FIT_CENTER);
holder.timer.setAdjustViewBounds(true);
holder.timer.setImageBitmap(bm3)
}
holder.mLinLayout.addView(holder.timer);
}
if (item.getUpdateFlag(3)) {
if (holder.log == null){
holder.log = new ImageView(convertView.getContext());
holder.log.setScaleType(ScaleType.FIT_CENTER);
holder.log.setAdjustViewBounds(true);
holder.log.setImageBitmap(bm4);
}
holder.mLinLayout.addView(holder.log);
}
if (item.getUpdateFlag(0)) {
if (holder.forward == null){
holder.forward = new ImageView(convertView.getContext());
holder.forward.setScaleType(ScaleType.FIT_CENTER);
holder.forward.setAdjustViewBounds(true);
holder.forward.setImageBitmap(bm5);
}
holder.mLinLayout.addView(holder.forward);
}
return convertView;
}
static class ViewHolder {
TextView name, value;
ImageView back, update, timer, log, forward;
LinearLayout mLinLayout;
}
}
即使我將LinearLayout
注釋掉,我也只有一個帶有兩個TextViews
的List。
所以我的問題。 我想念什么嗎? 一些愚蠢的事情? 如何使我的ListView更流暢? 順便說一句:我讀到一個不同的線程,如果ListView
具有android:cacheColorHint="#00000000
。我沒有此屬性。
我希望任何人都有解決方案。 謝謝!
關於GC調用的來源。 如果我正確理解您的代碼,則每次回收ListView項目並調用removeAllViews()
,都會刪除以前動態創建的ImageView
並將其Bitmap
進行垃圾回收。 因此,如果您使用相同的ImageView
在xml布局中聲明它,並且僅根據getUpdateFlag()
替換Bitmap
,也許可以避免那些GC調用。
還有關於ListViews和Images的兩件事。 第一件事是,如果圖像太大,無論如何,您的ListView都會變得遲鈍。 在這種情況下,您需要按比例縮小圖像( 有效地加載大位圖 )。 其次,也許您還需要實現一個懶惰列表,該懶惰列表按需加載圖像,對此有一個著名的問題-> 如何在ListView中進行圖像的延遲加載?
我終於解決了我的問題。 像上面一樣,我認為問題出在我列表項的圖像上。 但這不是問題。 我只是沒有正確使用ViewHolders
和getItemViewType(int position)
方法。 我有一個列表,其中包含許多不同的項目布局,並且我看到,上面的代碼為每個項目創建了一個新的convertView和一個新的ViewHolder,這是不應該的。 我找到了一個很棒的教程,介紹如何使用多個項目布局(請參見下面的鏈接):
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.