ArrayAdapter 中的错误 - 布局充气器抛出错误

Error in ArrayAdapter - layout inflator thows error

我在 Eclipse 中收到以下警告:

"Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling"

我使用的代码是:

class myadapter extends ArrayAdapter<String>
{
    Context context;
    int[] images;
    String[] mytitle;
    String[] mydescp;
    myadapter(Context c, String[] tittle, int[] imgs, String[] desc)
    {
        super(c, R.layout.single_row, R.id.listView1, tittle);
        this.context=c;
        this.images=imgs;
        this.mytitle= tittle;
        this.mydescp=desc;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflator.inflate(R.layout.single_row, parent, false);
        ImageView myImage = (ImageView) row.findViewById(R.id.imageView1);
        TextView myText = (TextView) row.findViewById(R.id.textView1);
        TextView mydesc = (TextView) row.findViewById(R.id.textView2);

        myImage.setImageResource(images[position]);
        myText.setText(mytitle[position]);
        mydesc.setText(mydescp[position]);

        return row;
    }
}

我在行中收到警告:View row = inflator.inflate(R.layout.single_row, parent, false);

它会导致我的 android 应用程序强制关闭...我现在该怎么办? 有什么建议吗???

您必须使用此代码

View row = convertView;

在这一行之前,

View row = inflator.inflate(R.layout.single_row, parent, false);

希望它有用..

嗨 Vinesh Senthilvel, 不用担心 使用我下面的代码,它肯定会解决你的问题,

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflator.inflate(R.layout.single_row, null, false);
        ImageView myImage = (ImageView) row.findViewById(R.id.imageView1);
        TextView myText = (TextView) row.findViewById(R.id.textView1);
        TextView mydesc = (TextView) row.findViewById(R.id.textView2);

        myImage.setImageResource(images[position]);
        myText.setText(mytitle[position]);
        mydesc.setText(mydescp[position]);

        return row;
    }

如果问题仍然存在,那么 post logcat 异常堆栈跟踪,我会帮助你

您需要回收 views.What android 因为系统只关心 visible.So 您必须回收未聚焦的行项目重新用于新项目。 或者想象一下所涉及的缓存量。

@Override
public View getView(int position, View row, ViewGroup parent) {
    // TODO Auto-generated method stub
    if(row==null){
     LayoutInflater inflator = (LayoutInflater)   context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflator.inflate(R.layout.single_row, parent, false);
  }

    ImageView myImage = (ImageView) row.findViewById(R.id.imageView1);
    TextView myText = (TextView) row.findViewById(R.id.textView1);
    TextView mydesc = (TextView) row.findViewById(R.id.textView2);

    myImage.setImageResource(images[position]);
    myText.setText(mytitle[position]);
    mydesc.setText(mydescp[position]);

    return row;
}

还有另一种方法,您只需要 import android.view.LayoutInflater; 并获取父级 (ViewGroup) 的上下文 - parent.getContext(),它将起作用

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    View v = LayoutInflater.from(parent.getContext()).inflate(
            R.layout.single_row, parent, false);

您应该重新使用视图而不是一次又一次地膨胀。这会降低性能。

根据您的代码,

 View row = inflator.inflate(R.layout.single_row, parent, false);

每次滚动时都会膨胀。为了最大化性能,请像

一样使用它
//re-use
if (row == null)
{
  inflate code here
}
else
{
  you already have a view `row`, just use it. 
}

您可以看到,第一次 row 将为 null & 它会膨胀并将其存储在视图 row 中。但是,从下一次开始,它不会一次又一次地膨胀,而是使用视图 row。 (重复使用)

"Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling"

这不是错误,它只是要求您使用 ViewHolder 模式的警告。让我来解释一下为什么它很重要。

没有 ViewHolder 模式:

  1. 第一次加载时,convertView为null。我们必须扩充我们的列表项布局并​​通过 findViewById().

  2. 找到 TextView
  3. 第二次加载,convertView不为null,good!我们不必再次给它充气。但我们将再次使用 findViewById()

  4. 以后加载的时候,convertView肯定不为null。但是 findViewById() 会不断被调用,它会起作用,但是会降低性能,尤其是当您的 ListView 中有很多项目和视图时。

使用 ViewHolder 设计模式:

  1. 第一次加载时,convertView为null。我们必须膨胀我们的列表项布局,实例化 ViewHolder,通过 findViewById() 找到 TextView 并将其分配给 ViewHolder,并将 ViewHolder 设置为 convertView 的标签。

  2. 第二次加载,convertView不为null,good!我们不必再次给它充气。这是一件好事,我们不必调用 findViewById(),因为我们现在可以通过其 ViewHolder 访问 TextView。

  3. 下次加载时,convertView肯定不为null。 findViewById() 再也不会被调用,这使得我们的 ListView 滚动流畅。

为什么要用?

您的代码可能会在 ListView 滚动期间频繁调用 findViewById(),这会降低性能。即使当 Adapter returns 一个用于回收的膨胀视图时,您仍然需要查找元素并更新它们。避免重复使用 findViewById() 的一种方法是使用 view holder 设计模式。

那么,什么是ViewHolder

一个 ViewHolder 对象将每个组件视图存储在 Layout 的标记字段中,因此您可以立即访问它们而无需重复查找它们。首先,您需要创建一个 class 来保存您的确切视图集。

如何使用?

  1. 创建一个单独的 class 作为 ViewHolder 并声明您使用的内容,如 EditText、TextView 等。

      static class ViewHolder {
      TextView text;
      TextView timestamp;
      ImageView icon;
      ProgressBar progress;
      int position;
      }
    
  2. 然后填充 ViewHolder 并将其存储在布局中。

     public View getView(int position, View convertView, ViewGroup parent) { 
             ViewHolder holder; 
    
             if (convertView == null) { // if convertView is null
                 convertView = mInflater.inflate(R.layout.mylayout, 
                         parent, false);
                 holder = new ViewHolder(); 
                     // initialize views  
                convertView.setTag(holder);  // set tag on view
            } else { 
                holder = (ViewHolder) convertView.getTag();
                        // if not null get tag 
                        // no need to initialize
            } 
    
            //update views here  
            return convertView; 
    }
    

来源:

Making ListView Scrolling Smooth from Android documentation

Android ViewHolder Pattern example