【问题标题】:Unable to use LayoutInflater in custom adapter无法在自定义适配器中使用 LayoutInflater
【发布时间】:2011-05-17 10:04:20
【问题描述】:

我正在考虑编写一个自定义适配器来填充一个列表视图,每行有 3 个文本视图。我找到了很多示例代码来执行此操作,但似乎最好的一个是:http://www.anddev.org/custom_widget_adapters-t1796.html

在对最新的 Android SDK 的一些编译器问题进行了一些小调整后,我让它运行起来了,只是得到了异常:

ERROR/AndroidRuntime(281): java.lang.UnsupportedOperationException: addView(View, LayoutParams) 在 AdapterView 中不受支持

所以我做了很多研究,发现了很多可能的原因和解决方法。这些都没有改变任何事情。我的适配器代码目前是:

public class WeatherAdapter extends BaseAdapter {

    private Context context;
    private List<Weather> weatherList;

    public WeatherAdapter(Context context, int rowResID,
                        List<Weather> weatherList ) { 
        this.context = context;
        this.weatherList = weatherList;
    }

    public int getCount() {                        
        return weatherList.size();
    }

    public Object getItem(int position) {     
        return weatherList.get(position);
    }

    public long getItemId(int position) {  
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) { 
        Weather weather = weatherList.get(position);

        //LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LayoutInflater inflater = LayoutInflater.from(context);

        View v = inflater.inflate(R.layout.weather_row, null, true);
        TextView cityControl = (TextView)v.findViewById( R.id.city );
        TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
        ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
        return v;
    }

}

所以我尝试了获取充气机的注释掉方法,以及当前未注释掉的方法。我曾尝试将“父级”传递给 inflate 以及 null,并传递“true”、“false”并完全省略最后一个参数。它们都没有奏效,到目前为止我发现的所有例子都是 2008 年的,我觉得有点过时了。

如果有人可以帮助解决这个问题,那么我很乐意解决这个问题。

【问题讨论】:

    标签: android android-layout listview android-xml android-adapter


    【解决方案1】:

    我认为这条线路有问题:

    View v = inflater.inflate(R.layout.weather_row, null, true);
    

    您需要:

    View v = inflater.inflate(R.layout.weather_row, parent, false);
    

    false 使膨胀视图独立于父视图,而不是附加到它,这很奇怪似乎是AdapterViews 中自定义视图的公认设计。为什么会这样,我觉得完全莫名其妙,但上面的模式对我有用。

    【讨论】:

    • 使用AdapterView 时,您希望您的视图独立于父级,getView() 会为您将其附加到父级。
    • @AustynMahoney 我不会说 getView() 会处理它,因为 是写它的人,我宁愿说 随便叫getView() (换句话说,框架)负责附加视图 getView()返回。
    【解决方案2】:

    我也是一个初学者,所以对这个答案持怀疑态度 - 如果它不起作用,请继续并谷歌更多。不熟悉AdapterView,因为我传统上有一个ListViewGridView 和一个从BaseAdapter 扩展的自定义适配器,然后是listView.setAdapter(myCustomAdapter)

    你可以尝试在 WeatherAdapter 类中做这样的事情:

    public void addToList(Weather mWeather) {
        weatherList.add(mWeather);
    }
    

    然后在调用WeatherAdapter的类中:

    weatherAdapter.addToList(weatherToAdd);
    weatherAdapter.notifyDataSetChanged();
    

    另外还需要在getView方法中进一步优化:

    http://www.youtube.com/watch?v=wDBM6wVEO70

    【讨论】:

      【解决方案3】:

      对于AdaptertView addView 方法:

      void addView(查看子)

      不支持此方法,并且 抛出一个 UnsupportedOperationException 时 调用。”(来自 Android 文档)

      可能膨胀过程调用了addView 方法,而这在AdapterView 或其AdapterView 中是不可能的。

      来自文档:

      "适配器对象充当桥梁 在 AdapterView 和 该视图的基础数据。这 适配器提供对数据的访问 项目。适配器也负责 为每个项目创建一个视图 数据集”。

      我认为膨胀操作可以通过一个简单的 Activity 来完成,该 Activity 对您的视图和所有其他操作进行建模,例如检索数据和在其他类中显示数据。

      希望对您有所帮助!

      【讨论】:

        【解决方案4】:

        @Axel22 的答案是关键,但您的代码中还缺少一些其他内容。首先,您应该扩展 BaseAdapter 或 ArrayAdapter,具体取决于您的偏好。其次,您希望练习使用 ViewHolder 以避免对 findViewById 进行过多调用,并(最重要的是)回收您的 View。

        private Class ViewHolder {
          public TextView cityControl;
          public TextView temperatureControl;
          public ImageView skyControl;
          public ViewHolder(TextView cityControl, TextView temperatureControl, ImageView skyControl) {
            this.cityControl = cityControl;
            this.temperatureControl = temperatureControl;
            this.skyControl = skyControl;
          }
        

        您的 getView 函数可以回收视图并利用 ViewHolder 类,如下所示:

        public View getView(int position, View convertView, ViewGroup parent) { 
            Weather weather = weatherList.get(position);
            // This is how you attempt to recycle the convertView, so you aren't 
            // needlessly inflating layouts.
            View v = convertView;
            ViewHolder holder;
            if (null == v) {
                v = LayoutInflater.from(getContext()).inflate(R.layout.weather_row, parent, false);
                TextView cityControl = (TextView)v.findViewById( R.id.city );
                TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
                ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
                holder = new ViewHolder(cityControl, temperatureControl, skyControl);
                v.setTag(holder);
            } else {
                holder = (ViewHolder) v.getTag();
            }
        
            holder.cityControl.setText("Metropolis");
            holder.temperatureControl.setText("78");
            holder.skyControl.setImageResource(R.drawable.daily_planet);
        
            return v;
        

        }

        如需更多示例(和其他优化技巧),请参阅 this blog post(或仅谷歌查看 ViewHolder)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多