Невозможно использовать LayoutInflater в пользовательском адаптере

Я собираюсь написать собственный адаптер для заполнения списка с тремя текстовыми представлениями на строку. Я нашел довольно много примеров кода для этого, но тот, который мне показался лучшим, был по адресу: http://www.anddev.org/custom_widget_adapters-t1796.html

После нескольких незначительных изменений, направленных на исправление некоторых проблем с компилятором с последним Android SDK, я запустил его только для того, чтобы получить исключение:

ОШИБКА / 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 году, и я чувствую, что они немного устарели.

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


person Teknogrebo    schedule 29.11.2010    source источник


Ответы (4)


Я тоже новичок, так что отнеситесь к этому ответу с долей скепсиса - если он не сработает, продолжайте и погуглите еще раз. Не знаком с AdapterView, так как у меня традиционно есть ListView или GridView и специальный адаптер, расширенный от 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

person albnok    schedule 19.01.2011

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

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

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

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

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

person Clint    schedule 21.06.2011
comment
При использовании AdapterView вы хотите, чтобы ваши представления были независимыми от родителя, getView() позаботится о том, чтобы прикрепить его к родителю за вас. - person Austyn Mahoney; 05.02.2013
comment
@AustynMahoney Я бы не сказал, что getView() позаботится об этом, поскольку вы это пишете, я бы предпочел любые вызовы getView() (другими словами, фреймворк) заботится о прикреплении представления , возвращенного getView(). - person Joffrey; 20.08.2014

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

void addView (дочерний вид)

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

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

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

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

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

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

person bifulcoluigi    schedule 28.05.2011

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

person mrmcduff    schedule 18.09.2013