Android:性能问题填充我的(复杂)ListView

时间:2014-06-09 17:09:58

标签: android performance listview

我有一个行列表,每行都有一份膳食列表。填充ListView的最佳方法是什么?这就是它现在的样子:http://imgur.com/dMEcVUF这是我的适配器:

public CanteenPlanAdapter(Context context, Plan plan) {
    this.context = context;
    if (plan != null) lines = plan.getLines();
}

@Override
public Object getItem(int position) {
    if (lines != null) return lines.get(position);
    else return null;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Line line = (Line) getItem(position);

    List<Meal> meals = line.getMeals();

    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.canteen_list_group_item, parent, false);

    for (int i = 0; i < meals.size(); i++) {

        Meal meal = meals.get(i);

        View child = inflater.inflate(R.layout.canteen_list_child_item, null);

        TextView name = (TextView) child.findViewById(R.id.canteen_meal_name);
        name.setText(meal.getMeal());

        TextView price = (TextView) child.findViewById(R.id.canteen_meal_price);
        price.setText(String.valueOf(meal.getPrice1()) + " €");

        if (meal.isBio()) {
            ImageView bio = (ImageView) child.findViewById(R.id.meal_bio);
            bio.setVisibility(1);
        }
        if (meal.isCow()) {
            ImageView cow = (ImageView) child.findViewById(R.id.meal_cow);
            cow.setVisibility(1);
        }
        if (meal.isCow_aw()) {
            ImageView cow_aw = (ImageView) child.findViewById(R.id.meal_cow_aw);
            cow_aw.setVisibility(1);
        }
        if (meal.isFish()) {
            ImageView fish = (ImageView) child.findViewById(R.id.meal_fish);
            fish.setVisibility(1);
        }
        if (meal.isPork()) {
            ImageView pork = (ImageView) child.findViewById(R.id.meal_pork);
            pork.setVisibility(1);
        }
        if (meal.isVeg()) {
            ImageView veg = (ImageView) child.findViewById(R.id.meal_veg);
            veg.setVisibility(1);
        }
        if (meal.isVegan()) {
            ImageView vegan = (ImageView) child.findViewById(R.id.meal_vegan);
            vegan.setVisibility(1);
        }
        ((ViewGroup) convertView).addView(child);
    }
    TextView name = (TextView) convertView.findViewById(R.id.canteen_line_name);
    convertView.setTag(name);

    name.setText(line.getName());

    return convertView;
}

它正在运行,但性能显然非常糟糕......我尝试使用Viewholder,但我不知道如何添加膳食列表项..

2 个答案:

答案 0 :(得分:0)

要在ListView中获得可接受的性能,必须重用项目视图。滚动时创建和销毁它们会使性能受到很大影响。所以第一部分是使用提供的convertView,当它不为空时(ViewHolder模式是对此的进一步优化)。

在这种情况下,额外的困难似乎在于每个列表项目也具有不同数量的子项,具体取决于成分。你应该做的是重用,如果你需要的东西比你已经拥有的多,那么只创建更多这些子视图(并将其他视图设置为GONE)。

一个粗略的例子(可能无法编译,仅作为指南使用):)

if (convertView == null)
    convertView = inflate(R.layout.canteen_list_group_item);

ViewGroup group = (ViewGroup)convertView;

for (int i = 0; i < meals.size(); i++)
{
    View child;
    if (group.getChildCount() > i)
    {
         // We have enough views already, recycle one.
         child = group.getChildAt(i);
    }
    else
    {
         // We need an extra row.
         child = inflate(...);
         group.addView(child);
    }

    setVisibility(View.VISIBLE); // in case it was hidden previously.

    // Load this child
    TextView name = (TextView) child.findViewById(R.id.canteen_meal_name);
    <etc, same as before>
}

// Hide extra children
for (int i = meals.size(); i < group.getChildCount(); i++)
    group.getChildAt(i).setVisibility(View.GONE);

return group;

当然,如果canteen_list_group_item有其他“固定”子视图,则可能必须调整索引(即不从0开始),但我希望你明白这一点。

答案 1 :(得分:0)

首先感谢你的小鸡回应!我根据你的想法更改了我的代码并且它正在工作(有点)。 canteen_list_group_item有2个固定的子视图(名称和分隔线)所以我调整了索引:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    Line line = (Line) getItem(position);
    List<Meal> meals = line.getMeals();

    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.canteen_list_group_item, parent, false);
    }
    ViewGroup group = (ViewGroup) convertView;

    for (int i = group.getChildCount(); i < meals.size() + 2; i++) {

        Meal meal = meals.get(i - 2);

        View child;
        if (group.getChildCount() > i) {
            child = group.getChildAt(i);
        } else {
            child = LayoutInflater.from(context).inflate(R.layout.canteen_list_child_item, null);
            group.addView(child);
        }
        child.setVisibility(View.VISIBLE);

        TextView name = (TextView) child.findViewById(R.id.canteen_meal_name);
        name.setText(meal.getMeal());

        TextView price = (TextView) child.findViewById(R.id.canteen_meal_price);
        price.setText(String.valueOf(meal.getPrice1()) + " €");

    }
    for (int i = meals.size() + 2; i < group.getChildCount(); i++) {
        group.getChildAt(i).setVisibility(View.GONE);
    }

    TextView name = (TextView) convertView.findViewById(R.id.canteen_line_name);
    convertView.setTag(name);

    name.setText(line.getName());

    return convertView;
}

我现在的问题是,儿童用品似乎随机出现或消失在他们的小组中,没有什么是按顺序“按顺序”。我的代码中有错误或错过了什么吗?