Подтвердить что ты не робот

Почему getView возвращает неверные объекты convertView в SeparatedListAdapter?

Я адаптировал SeparatedListAdapter от Джеффа Шарки к моим потребностям и получил что-то вроде этого:

public class SeparatedListAdapter<T> extends BaseAdapter {

    @SuppressWarnings("unused")
    private final String LOG_TAG = getClass().getSimpleName();

    public final static int TYPE_SECTION_HEADER = 0;

    public final Map<T, Adapter> sectionAdapters;
    public final ArrayAdapter<T> headerAdapter;

    public SeparatedListAdapter(ArrayAdapter<T> headerAdapter) {
        super();
        this.sectionAdapters = new LinkedHashMap<T,Adapter>();
        this.headerAdapter = headerAdapter;
    }

    public void addSection(T section, Adapter adapter) {
        this.headerAdapter.add(section);
        this.sectionAdapters.put(section, adapter);
    }

    public void clearSections() {
        this.headerAdapter.clear();
        this.sectionAdapters.clear();
    }

    @Override
    public int getCount() {
        // total together all sections, plus one for each section header
        int total = 0;
        for(Adapter adapter : this.sectionAdapters.values())
            total += adapter.getCount() + 1;
        return total;
    }

    @Override
    public int getViewTypeCount() {
        //count headers, then total all sections
        int total = this.headerAdapter.getViewTypeCount();
        for(Adapter adapter : this.sectionAdapters.values())
            total += adapter.getViewTypeCount();
        return total;
    }

    @Override
    public int getItemViewType(int position) {
        int type = 1;
        for(Object section : this.sectionAdapters.keySet()) {
            Adapter adapter = sectionAdapters.get(section);
            int size = adapter.getCount() + 1;

            // check if position inside this section 
            if(position == 0) return TYPE_SECTION_HEADER;
            if(position < size) return type + adapter.getItemViewType(position - 1);

            // otherwise jump into next section
            position -= size;
            type += adapter.getViewTypeCount();

        }
        return -1;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        int sectionnum = 0;
        for(Object section : this.sectionAdapters.keySet()) {
            Adapter adapter = sectionAdapters.get(section);
            int size = adapter.getCount() + 1;

            // check if position inside this section 
            if(position == 0) 
                return headerAdapter.getView(sectionnum, convertView, parent);
            if(position < size) 
                return adapter.getView(position - 1, convertView, parent);

            // otherwise jump into next section
            position -= size;
            sectionnum++;
        }
        return null;
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return (getItemViewType(position) != TYPE_SECTION_HEADER);
    }
}

Проблема, с которой я столкнулся, заключается в том, что API передает объекты onvertView с неправильного адаптера в getView(), что приводит к проблемам. Я думаю, что я правильно реализовал getViewTypeCount() и getItemViewType() и проверил это с помощью отладчика. Что еще может пойти не так?

Вот один из моих адаптеров:

public static class MeetingAdapter extends ArrayAdapter<Meeting> {
    static class ViewHolder {
        TextView title;
    }
    private LayoutInflater inflater;

    public MeetingAdapter(Activity context, List<Meeting> meetings) {
        super(context, 0, meetings);
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Meeting meeting = getItem(position);

        View rowView = convertView;
        ViewHolder holder;

        // instanceof should not be necessary!!! normally convertView should be of the right type!
        if (rowView == null || !(rowView.getTag() instanceof ViewHolder)) {
            rowView = inflater.inflate(R.layout.list_item, null);
            holder = new ViewHolder();
            holder.title = (TextView)rowView; // tmp - layout contains only a textview for the moment
            rowView.setTag(holder);
        } else {
            holder = (ViewHolder)rowView.getTag();
        }
        holder.title.setText(meeting.getTrack());
        return rowView;
    }
}

Помогите пожалуйста? Исходя из этого.

4b9b3361

Ответ 1

Я проследил эту проблему как объект списка RecybleBin listviews. Он хранит возможные конверсии на основе их зарегистрированных типов из getItemViewType, однако его содержимое никогда не обновляется после изменения набора данных (таким образом, позиции), а затем, когда ваш адаптер получает то, что раньше было типом "X", основанным на его позиции, но теперь это тип "Y". Решение состоит в том, чтобы вручную проверить getView, что не только convertView имеет значение null, но, тем не менее, он имеет правильный тип (что действительно неудобно иногда... Если вы используете шаблон держателя вида, вы можете проверить, соответствует ли тег соответствующему классу зрителя )