gpt4 book ai didi

android - ListView 性能很慢

转载 作者:搜寻专家 更新时间:2023-11-01 08:56:49 27 4
gpt4 key购买 nike

我有一个自定义的 ListView,我在其中显示了一些从本地数据库检索到的武器。我总共有 88 行,每次调用 getView() 时,每行都会设置一个文本和一个图像。 ListView 在快速滚动时滞后,垃圾收集器变得疯狂,每秒删除大约 1M 对象。我不明白为什么。

在我发布我的Adapter 实现之前,先解释一下如何设置图像。我的 Weapon 类只是一个带有 setter 和 getter 的数据容器。这就是创建数据库时设置名称和图像的方式(是的,这可能看起来很奇怪,但所有其他解决方案的工作速度甚至更慢):

    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 始终指向我的 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);
}

}

但是,当上下滚动整个 List 时,GC 仍然会疯狂调用并且 RAM 消耗会增加。现在的问题是:如何优化图像回收以避免 RAM 使用量增加?

最佳答案

由于将所有位图加载到 Android 内存中通常是不切实际的,因此您应该假设您会时不时地遇到 GC。

但是,您可以考虑以下提示:

  1. 将位图缩小到显示它们所需的大小。你可以使用 google's waymy way .

  2. 检查您将图像文件放在哪个文件夹中。许多人将它们放在 res/drawable 文件夹中,但不明白为什么它们会比原始尺寸大很多(这是因为密度 - 它是 mdpi,而设备可能是 xhdpi 或 xxhdpi)。

    例如,如果图像位于可绘制文件夹中,并且您在 xhdpi 设备(如 galaxy S3)上运行它,则需要 (WIDTH*2)*(HEIGHT*2)*4 字节。如果图像是 200x200,它的位图对象至少需要 400*400*4=640,000 字节。它在 xxhdpi 设备上会更糟,比如 galaxy s4 和 htc one。

  3. 考虑使用内存缓存,例如 LruCache

  4. 如果位图没有透明度,并且您看不到任何质量差异,请考虑使用 RGB_565 config而不是默认的。这将占用每个像素 2 个字节,而不是每个像素 4 个字节。

  5. 如果您足够负责,可以使用 JNI 进行缓存。我为此任务制作了一个小代码,here .请阅读我在那里写的所有笔记。

顺便说一句,我注意到您为图像使用了一组标识符。如果图像的名称中有一些逻辑(例如:img1、img2、...),您可以改用 getResources().getIdentifier(...)。

关于android - ListView 性能很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18424864/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com