Почему getView возвращает неправильные объекты convertView в SeparatedListAdapter?
Я адаптировал SeparatedListAdapter от Jeff Sharkey к своим потребностям и получил что-то вроде этого:
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;
}
}
Помогите, пожалуйста? Схожу с ума по этому поводу.
1 ответ
Я проследил проблему до объекта RecybleBin в listviews. Он хранит возможные convertViews на основе их сообщенных типов из getItemViewType, однако его содержимое никогда не обновляется после изменения набора данных (таким образом, позиций), а затем, когда ваш адаптер получает то, что раньше было представлением типа "X", на основе его позиции, но теперь это происходит с типом "Y". Решение состоит в том, чтобы вручную проверить getView, не только ли convertView имеет значение null, но и имеет ли он правильный тип (иногда это очень неудобно... Если вы используете шаблон держателя вида, вы можете проверить, соответствует ли тег вашему соответствующему классу держателя представления.)