无条件的布局膨胀:应使用“视图持有人"模式 [英] Unconditional layout inflation: Should use View Holder pattern

查看:51
本文介绍了无条件的布局膨胀:应使用“视图持有人"模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新手,我试图给项目行充气,但是滚动时它会使应用程序变慢.在下面的代码中,它说我需要使用View Holder.

I'm a newbie, I tried to inflate the item row but it slows the application upon scrolling. In the code below, it says I need to use View Holder.

        row = inflater.inflate(mLayoutResourceId, parent, false);

我该如何解决?

package com.example.android.ontrack.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.example.android.ontrack.R;
import com.example.android.ontrack.models.Order;

public class OrdersList extends ArrayAdapter<Order> {

    Context mContext;
    int mLayoutResourceId;
    Order mData[] = null;

    public OrdersList(Context context, int resource, Order[] data) {
        super(context, resource, data);
        this.mContext = context;
        this.mLayoutResourceId = resource;
        this.mData = data;
    }


    @Override
    public Order getItem(int position) {
        return super.getItem(position);
    }

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

        LayoutInflater inflater = LayoutInflater.from(mContext);
        row = inflater.inflate(mLayoutResourceId, parent, false);

            TextView nameOfSchool = row.findViewById(R.id.school_name_orders);
        TextView nameOfAgent = row.findViewById(R.id.agent_name);
        TextView orderId = row.findViewById(R.id.order_id);
        TextView netRevenue = row.findViewById(R.id.net_revenue);
        TextView orderQuantity = row.findViewById(R.id.total_quantity);
        TextView date = row.findViewById(R.id.date);

        Order orders = mData[position];

        nameOfSchool.setText(orders.nameOfSchool);
        nameOfAgent.setText(String.valueOf(orders.nameOfAgent));
        orderId.setText(String.valueOf(orders.orderId));
        netRevenue.setText(String.valueOf(orders.netRevenue));
        orderQuantity.setText(String.valueOf(orders.totalQuantity));
        date.setText(String.valueOf(orders.date));

        return row;
    }
}

推荐答案

您的问题出在以下代码中:

Your problem is in this bit of code:

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

    LayoutInflater inflater = LayoutInflater.from(mContext);
    row = inflater.inflate(mLayoutResourceId, parent, false);

    ...
    return row;
}

警告消息说,无论系统将什么传递给getView(),您始终会调用inflater.inflate()来生成row.

The warning message is saying that, no matter what gets passed by the system to getView(), you're always calling inflater.inflate() to generate your row.

首先要了解的是,传递给getView()convertView参数有时为null,有时不是null. 不为空时,它是以前从getView()返回的旧"(回收")视图.换句话说,这就是您自己膨胀的视图的类型,只是其中包含旧数据.

The first thing to understand is that the convertView param passed to getView() is sometimes null, and sometimes not. When it is not null, it is an "old" ("recycled") view that was previously returned from getView(). In other words, it's the exact same type of view that you'd inflate yourself, it just has old data in it.

因此,您可以通过将上面的代码改为以下内容来解决该问题:

So, you can fix that problem by changing the above code to this instead:

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

    if (convertView == null) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        row = inflater.inflate(mLayoutResourceId, parent, false);
    } else {
        row = convertView;
    }

    ...
    return row;
}

要理解的第二件事是findViewById()很慢.不像慢几秒钟,而是慢到足以使您不得不运行数百次,这会导致UI滞后.因此,视图持有者模式"是一种避免每次都要查找这些视图的方法.

The second thing to understand is that findViewById() is slow. Not like multiple seconds slow, but slow enough that if you have to run it hundreds of times it will cause your UI to lag. So the "view holder pattern" is a way for you to avoid having to look up these views every time.

您要做的第一件事是创建一个类,其中包含行中每个视图的字段.鉴于您发布的内容,看起来应该像这样:

The first thing you do is create a class that has fields for each view in your row. Given what you posted, that would look something like this:

private static class ViewHolder {

    private final TextView nameOfSchool;
    private final TextView nameOfAgent;
    private final TextView orderId;
    private final TextView netRevenue;
    private final TextView orderQuantity;
    private final TextView date;

    private ViewHolder(View row) {
        nameOfSchool = row.findViewById(R.id.school_name_orders);
        nameOfAgent = row.findViewById(R.id.agent_name);
        orderId = row.findViewById(R.id.order_id);
        netRevenue = row.findViewById(R.id.net_revenue);
        orderQuantity = row.findViewById(R.id.total_quantity);
        date = row.findViewById(R.id.date);
    }
}

现在,您必须将其插入到您的getView()代码中.每次给视图充气时(例如,当convertView为null时),您都需要创建一个新的ViewHolder,否则,您将希望重用现有的ViewHolder.为此,我们使用视图的标签.

Now you have to plug it in to your getView() code. You will want to create a new ViewHolder every time you inflate a view (i.e. when convertView is null), and you'll want to re-use an existing ViewHolder otherwise. We use the view's tag for this.

总的来说,看起来像这样:

All together, it looks like this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row;
    ViewHolder holder;

    if (convertView == null) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        row = inflater.inflate(mLayoutResourceId, parent, false);
        holder = new ViewHolder(row);
        row.setTag(holder);       
    } else {
        row = convertView;
        holder = (ViewHolder) row.getTag();
    }

    Order orders = mData[position];

    holder.nameOfSchool.setText(orders.nameOfSchool);
    holder.nameOfAgent.setText(String.valueOf(orders.nameOfAgent));
    holder.orderId.setText(String.valueOf(orders.orderId));
    holder.netRevenue.setText(String.valueOf(orders.netRevenue));
    holder.orderQuantity.setText(String.valueOf(orders.totalQuantity));
    holder.date.setText(String.valueOf(orders.date));

    return row;
}

这篇关于无条件的布局膨胀:应使用“视图持有人"模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆