【问题标题】:Error in ArrayAdapter - layout inflator thows errorArrayAdapter 中的错误 - 布局充气机引发错误
【发布时间】:2015-02-19 04:47:25
【问题描述】:

在 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 应用程序强制关闭...我现在该怎么办? 有什么建议???

【问题讨论】:

    标签: android android-arrayadapter layout-inflater


    【解决方案1】:

    您需要回收您的视图。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;
    }
    

    【讨论】:

      【解决方案2】:

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

      根据您的代码,

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

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

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

      没有ViewHolder 模式:

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

      2. 第二次加载,convertView不为空,好!我们不必再给它充气。但我们会再次使用findViewById()

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

      使用ViewHolder 设计模式:

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

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

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

      为什么要使用?

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

      那么,ViewHolder 是什么?

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

      如何使用?

      1. 创建一个单独的类作为 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

      【讨论】:

        【解决方案3】:

        嗨,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 异常堆栈跟踪,我会帮助你

        【讨论】:

        • 查看行 = inflator.inflate(R.layout.single_row, null, false);
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          您必须使用此代码

          View row = convertView;
          

          在这一行之前,

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

          希望它有效..

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-08-15
          • 1970-01-01
          • 1970-01-01
          • 2012-05-03
          • 2014-06-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多