无条件布局膨胀:应使用View Holder模式

我是新手,我试图给项目行充气但是在滚动时它会减慢应用程序的速度。 在下面的代码中,它说我需要使用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 { 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; } } 

你的问题在于这段代码:

 @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

首先要理解的是传递给getView()convertView参数有时是null,有时不是。 如果它不为null ,则它是先前从getView()返回的“旧”(“循环”)视图。 换句话说,它是你自己膨胀的完全相同类型的视图,它只包含旧数据。

因此,您可以通过将以上代码更改为此来解决此问题:

 @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滞后。 因此,“视图持有者模式”是一种让您无需每次都查看这些视图的方法。

您要做的第一件事是创建一个类,该类包含行中每个视图的字段。 根据你发布的内容,看起来像这样:

 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 。 我们使用视图的标签。

总之,它看起来像这样:

 @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; } 

由于层次计算和其他一些事情,布局膨胀可能非常耗时,这就是为Android引入RECYCLING视图平台的原因。

您创建一次视图,当它不再使用时,它可以被回收。 所以它只需要将数据绑定到视图。

视图持有者是视图的包装器,它是持有ref的视图。 要重新使用的视图。 您可以在RecyclerView上查看这些单页教程,这是一个更灵活,更高效的ListView版本

https://developer.android.com/training/material/lists-cards.html