【问题标题】:Why does getView return wrong convertView objects on SeparatedListAdapter?为什么 getView 在separatedListAdapter 上返回错误的convertView 对象?
【发布时间】:2012-08-14 16:21:33
【问题描述】:

我根据自己的需要调整了 Jeff Sharkey 的 SepatedListAdapter,得到了类似这样的东西:

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

请帮忙?对此感到疯狂。

【问题讨论】:

  • 我遇到了同样的问题,标题视图被提供给适配器,反之亦然:/尤其是在更新数据并调用 notifyDatasetChanged 之后
  • 很好的解决方法,谢谢。
  • 我很惊讶这没有更多的支持。

标签: android listview android-arrayadapter convertview


【解决方案1】:

我发现问题出在列表视图的 RecybleBin 对象上。它根据从 getItemViewType 报告的类型存储可能的 convertViews,但是在您更改数据集(因此位置)之后,它的内容永远不会更新,然后当您的适配器根据其位置获取过去的类型“X”视图时,但是现在它恰好是“Y”类型。 一种解决方案是手动检查 getView 是否不仅 convertView 为空,而且它的类型是否正确(有时这真的很尴尬......如果您使用视图持有者模式,您可以检查标签是否与相应的视图持有者类匹配)

【讨论】:

  • 哦,当我继续前进时,我没有看到此回复,只是使用了解决方法(与您提出的相同,请参阅我的代码)。很高兴听到我不是唯一一个!
  • 我很快就会为此发疯。谢谢你:)
  • 回收站根据最初从 getItemViewType 读取但随后保存到视图的 LayoutParams 对象的类型在技术上存储转换视图。如果您覆盖视图的 LayoutParams,您将覆盖视图类型,从而破坏回收!
猜你喜欢
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 2017-04-26
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多