Невозможно использовать LayoutInflater в пользовательском адаптере - PullRequest
8 голосов
/ 29 ноября 2010

Я пытаюсь написать собственный адаптер, чтобы заполнить представление списка тремя текстовыми представлениями в строке.Я нашел довольно много примеров кода, чтобы сделать это, но тот, который казался лучшим, был по адресу: 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;
    }

}

Итак, я попробовал закомментированный способ получения инфлятора и текущий закомментированный.Я попытался передать «parent», чтобы завышать, а также null, и передать «true», «false» и полностью опустить последний параметр.Ни один из них не сработал, и все примеры, которые я нашел до сих пор, были с 2008 года, и я чувствую, что они немного устарели.

Если кто-то может помочь с этим, тогда я бы с удовольствием решил эту проблему.

Ответы [ 4 ]

16 голосов
/ 21 июня 2011

Я считаю, что эта строка ошибочна:

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

Вместо этого вам нужно:

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

Значение false делает раздутое представление независимым от родителя, не привязанным к нему, чтоочень странно, кажется, принятый дизайн для пользовательских представлений в пределах AdapterView с.Почему это так, я нахожу совершенно непонятным, но шаблон выше работал для меня.

6 голосов
/ 19 января 2011

Я тоже новичок, так что примите этот ответ с щепоткой соли - если это не сработает, продолжайте и Google еще немного.Не знаком с AdapterView, поскольку у меня традиционно есть ListView или GridView и пользовательский адаптер, расширенный от BaseAdapter, а затем listView.setAdapter(myCustomAdapter).

. Вы можете попробовать сделать что-то подобное внутри WeatherAdapter class:

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

Затем в классе, который вызывает WeatherAdapter:

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

Также вам нужно оптимизировать его больше в методе getView:

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

3 голосов
/ 28 мая 2011

Для метода AdaptertView addView:

void addView (View child)

Этот метод не поддерживается и бросает UnsupportedOperationException, когда звонил. "(Из документации Android)

Возможно, процедура накачивания вызывает метод addView, и это невозможно из AdapterView или AdapterView.

Из документации:

"Объект-адаптер действует как мост между AdapterView и основные данные для этого представления. Адаптер обеспечивает доступ к данным Предметы. Адаптер также несет ответственность для создания представления для каждого элемента в набор данных ".

Я думаю, что операция надувания может быть выполнена из простого действия, которое моделирует ваше представление и все другие операции, например, получение данных и отображение данных в других классах.

Надеюсь, это будет полезно!

1 голос
/ 18 сентября 2013

@ Ответ 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;

}

Чтобы найти множество других примеров (и других советов по оптимизации), см. этот пост (или просто Google для ViewHolder).

...