ListView
ローカル データベースから取得したいくつかの武器を表示するカスタムがあります。getView()
合計 88 行あり、行ごとにテキストと画像が呼び出されるたびに設定されます。高速スクロール中ListView
に遅延が発生し、ガベージ コレクターが異常になり、1 秒あたり 1M オブジェクトが削除されます。理由がわかりません。
実装を投稿する前にAdapter
、イメージの設定方法について説明します。私のWeaponクラスは、セッターとゲッターを持つ単なるデータホルダーです。これは、データベースが作成されるときに名前と画像が設定される方法です (非常に奇妙に思えるかもしれませんが、他のすべてのソリューションはさらにゆっくりと動作します)。
private Weapon buildWeapon(Cursor cursor) {
Weapon w = new Weapon();
w.setId(cursor.getLong(0));
w.setName(cursor.getString(1));
w.setImage(Constants.ALL_WEAPON_IMAGES[(int) cursor.getLong(0)-1]);
return w;
}
そのため、Array
すべての武器の画像を の形式で含む がありR.drawable.somegun
ます。データ構造は、ID-1 が常に my の正しいドローアブル参照を指すように実装されていArray
ます。Weapon クラスの画像フィールドはInteger
. これで、私の方法がどのように機能するかがわかりました。getImage()
以下は私の方法Adapter
です。
public class Weapon_Adapter extends BaseAdapter {
private List<Weapon> items;
private LayoutInflater inflater = null;
private WeaponHolder weaponHolder;
private Weapon wp;
static class WeaponHolder {
public TextView text;
public ImageView image;
}
// Context and all weapons of specified class are passed here
public Weapon_Adapter(List<Weapon> items, Context c) {
this.items = (List<Weapon>) items;
inflater = LayoutInflater.from(c);
Log.d("Adapter:", "Adapter created");
}
@Override
public int getCount() {
return items.size();
}
@Override
public Weapon getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
wp = (Weapon) getItem(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.category_row, null);
weaponHolder = new WeaponHolder();
weaponHolder.text = (TextView) convertView
.findViewById(R.id.tvCatText);
weaponHolder.image = (ImageView) convertView
.findViewById(R.id.imgCatImage);
convertView.setTag(weaponHolder);
}
weaponHolder = (WeaponHolder) convertView.getTag();
weaponHolder.text.setText(wp.getName());
weaponHolder.image.setImageResource(wp.getImage());
// weaponHolder.image.setImageResource(R.drawable.ak74m);
return convertView;
}}
奇妙なことに、コメントアウトされた行を使用してすべてのアイテムに同じ画像を静的に設定すると、一度も呼び出されずにすべてのラグと GC が削除されます! 私はそれを得ていません..wp.getImage()
まったく同じものを返しますが、R.drawable.name
武器ごとに異なるだけです。しかし、GC はListView
スクロール中に大量のオブジェクトとラグを取り除きます。私が間違っていることはありますか?
アップデート
画像の設定をに移動しましたがAsyncTask
、ラグはなくなりました:
public class AsyncImageSetter extends AsyncTask<Void, Void, Void> {
private ImageView img;
private int image_resId;
private Bitmap bmp;
private Context c;
public AsyncImageSetter(Context c, ImageView img, int image_ResId, Bitmap bmp) {
this.img = img;
this.image_resId = image_ResId;
this.bmp = bmp;
this.c = c;
}
@Override
protected Void doInBackground(Void... params) {
bmp = BitmapFactory.decodeResource(c.getResources(), image_resId);
return null;
}
@Override
protected void onPostExecute(Void result) {
img.setImageBitmap(bmp);
bmp = null;
super.onPostExecute(result);
}
}
ただし、GC は依然として狂ったように呼び出され、リスト全体を上下にスクロールすると RAM の消費量が増加します。問題は、RAM 使用量の増加を回避するためにイメージのリサイクルを最適化するにはどうすればよいかということです。