ArrayAdapter中的错误 - layoutinflater抛出错误

时间:2015-02-19 04:47:25

标签: android android-arrayadapter layout-inflater

我在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;
    }
}

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

它导致我的Android应用程序强制关闭......我现在能做什么? 任何建议???

5 个答案:

答案 0 :(得分:2)

您需要回收您的视图。系统关心的android只是可见的项目。因此,您必须回收未关注的行项目以重新用于新项目。 或者想象一下所涉及的缓存量。

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

答案 1 :(得分:1)

你应该重复使用视图而不是一次又一次地膨胀。这降低了性能。

从您的代码中

 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第一次为空&amp;它会在视图row中充气并存储它。但是,从下一次开始,它不会一次又一次地膨胀,而是使用View row。 (重复利用)

  

“来自视图适配器的无条件布局膨胀:应使用View Holder模式(使用传递给此方法的循环视图作为第二个参数)以实现更流畅的滚动”

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

没有ViewHolder模式:

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

  2. 第二次加载时,convertView不为null,好!我们不必再次膨胀它。但我们会再次使用findViewById()

  3. 以下次加载时,convertView绝对不是null。但findViewById()经常被调用,它会起作用,但它会降低性能,特别是如果你的ListView中有很多项目和视图。

  4. 使用ViewHolder设计模式:

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

    2. 第二次加载时,convertView不为null,好!我们不必再次膨胀它。这是最好的事情,我们不必调用findViewById(),因为我们现在可以通过ViewHolder访问TextView。

    3. 以下时间加载,convertView绝对不是null。 findViewById()永远不会再被调用,这使得我们顺利地滚动ListView。

    4. 为什么要使用?

      在滚动ListView期间,您的代码可能会经常调用findViewById(),这会降低性能。即使适配器返回一个膨胀的视图以进行回收,您仍然需要查找元素并更新它们。围绕重复使用findViewById()的方法是使用view holder设计模式。

      那么,ViewHolder是什么?

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

      如何使用?

      1. 创建一个单独的类ViewHolder&amp;声明你使用的是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; 
        }
        
      3. 来源:

        Making ListView Scrolling Smooth from Android documentation

        Android ViewHolder Pattern example

答案 2 :(得分:0)

您必须使用此代码

View row = convertView;

在这一行之前,

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

希望它有效..

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

还有另一种方法,您只需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);