无法在自定义适配器中使用LayoutInflater

时间:2010-11-29 17:29:13

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

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

经过一些小的调整来修复最新的Android SDK的一些编译器问题后,我让它运行,只是为了得到例外:

  

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

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

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

}

所以我已经尝试了注释的方式来获取inflater,并且当前没有注释掉。我已经尝试将“父”传递给inflate以及null,并传递“true”,“false”并完全省略最后一个参数。他们都没有工作,到目前为止我发现的所有例子都是从2008年开始的,我感觉有点过时了。

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

4 个答案:

答案 0 :(得分:16)

我相信这条线是错的:

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

您需要:

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

false使得膨胀的视图独立于父级,而不是附加到父级,这在奇怪的情况下似乎是AdapterView中自定义视图的可接受设计。为什么会这样,我觉得完全莫名其妙,但上面的模式对我有用。

答案 1 :(得分:6)

我也是初学者也是如此,所以只需要一点点盐就可以得到这个答案 - 如果它不起作用,继续前进,谷歌会更多。不熟悉AdapterView,因为我传统上有ListViewGridView,自定义适配器扩展到BaseAdapter然后listView.setAdapter(myCustomAdapter)

您可以尝试在WeatherAdapter类中制作类似的内容:

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

然后在调用WeatherAdapter的课程中<:p>

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

您还需要在getView方法中对其进行更多优化:

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

答案 2 :(得分:3)

对于AdaptertView addView方法:

  

void addView(View child)

     

不支持此方法   抛出一个   UnsupportedOperationException时   叫。“(来自Android文档)

膨胀程序可能会调用addView方法,但AdapterView或其AdapterView无效。

来自文档:

  

“Adapter对象充当桥梁   在AdapterView和。之间   该视图的基础数据。该   适配器提供对数据的访问   项目。适配器也负责   为每个项目制作一个视图   数据集“。

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

希望它会有所帮助!

答案 3 :(得分:1)

@ 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(或只是google for ViewHolder)。