【问题标题】:bad convertView type BaseAdapter of ListViewListView 的转换视图类型 BaseAdapter 错误
【发布时间】:2011-12-08 18:46:04
【问题描述】:

我有一个列表视图适配器,它使用不同类型的视图行。

大多数时候它工作正常。但是当我从列表中删除一个元素时,它会崩溃。它向 getView 发送一个不正确类型的 convertView

public View getView(int position, View convertView, ViewGroup patent) ...  

但 getItemViewType 返回的是正确的类型。

public int getItemViewType(int position)

所以我看到了类似这样的东西

给我位置 1 的类型 -> 返回正确的类型(比如 1)

给我一​​个位置 1 的视图,其中包含错误类型(比如类型 2)的内容视图。

有什么想法吗?

【问题讨论】:

  • 发布您的getView()getItemViewType()

标签: android listview listview-adapter


【解决方案1】:

尝试覆盖 getViewTypeCount()

@Override
public int getViewTypeCount() {
       return types;
}

返回 getView(int, View, ViewGroup) 将创建的 View 类型的数量。每种类型代表一组可以在 getView(int, View, ViewGroup) 中转换的视图。

【讨论】:

  • 注意这个答案!它解决了我的转换视图类型错误的问题。现在 convertView 要么是正确的视图类型,要么是 null。
  • 在我的情况下,我确保我实现了这个,但之后我复制粘贴了一些方法并意外删除了它。谢谢指点。
  • 这个答案本身并不能解决问题,至少在 Android 4.4.2 上没有。 getView 有时仍会得到错误类型的 convertView。
  • 没关系,这个答案很好。我看到作为 convertView 传递的视图类型错误,因为我覆盖了视图的 AbsListView.LayoutParams 变量。这是回收器在确定将已删除视图 (AbsListView.LayoutParams.viewType) 保存在何处时所查看的位置。
【解决方案2】:

当实现正确时,ListView保证作为convertView提供的视图来自正确的Type

     /**
     * @return A view from the ScrapViews collection. These are unordered.
     */
    View getScrapView(int position) {
        if (mViewTypeCount == 1) {
            return retrieveFromScrap(mCurrentScrap, position);
        } else {
            int whichScrap = mAdapter.getItemViewType(position);
            if (whichScrap >= 0 && whichScrap < mScrapViews.length) {
                return retrieveFromScrap(mScrapViews[whichScrap], position);
            }
        }
        return null;
    }

您应该覆盖getViewTypeCount(),返回您拥有的视图类型的数量并覆盖getItemViewType(int position),返回范围从0到getViewTypeCount() - 1的视图类型

【讨论】:

  • 这并不完全正确。在 JellyBean 之前的构建中,当 Adapter 的数据集发生更改,导致视图重新排序时,getViewType() 仍会为每一行正确返回,但提供给该行的 convertView 可能是错误的类型。您需要在 getView() 中检查 convertView 的类型。
【解决方案3】:

这很正常,如果你在convertView 中得到一个不同类型的View,你会创建一个new View,而不是重复使用convertView

可能没有给定类型的可重用视图。

注意:此答案来自2011,可能不再适用。

【讨论】:

  • 有一个回收站持有视图。如果它是错误的类型,如果你不使用它,你可能会泄漏。
  • 回收器将测试您从 #getView(int, View, ViewGroup) 返回的 View 是否为 convertView - 如果不是,则 convertView 将被放回回收器以供以后重用或报废.基本上 - 它不应该泄漏(并且不会泄露) - 所以 Varga Péter 是正确的。
  • 我不再认为这是答案。请参阅这篇说始终使用内容视图的帖子。 groups.google.com/group/android-developers/browse_thread/thread/…
  • 很公平(您的意思是在问题和评论中转换视图也对吗?),但坦率地说,Android 库充满了这些小错误,所以我只是假设这是另一种情况。 ..但是解决方案是a)不要使用convertView,最坏的情况是“泄漏”它,这最坏的情况意味着泄漏的视图与从列表中删除的视图一样多,我猜这是用户发起的操作... b) 深入研究 Android BaseAdapter 实现并修复此错误,然后要求每个用户升级他们的手机(???) c) 编写自己的不会泄漏的 ListView 克隆。
  • ListView 运行良好,开发人员密切关注回收器。 “答案”只是充满了假设,没有具体的代码参考支持。 @Santhosh 的回答将解决遇到的问题
【解决方案4】:

我遇到了同样的问题,它导致了崩溃或意外行为。
这就是我解决问题的方法:

    getViewTypeCount() 应该返回视图中不同类型的行数
    getItemViewType(...) 应该返回位置项的类型
    getView(...) 应该在膨胀时在视图上设置枚举类型
@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return mlistItems.get(position).type.ordinal();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ListItem item = mListems.get(position);

    if (convertView == null) {
        switch (item.type) {
            case Header:
                converview = // Inflate Header Row
                break;
            case Content:
                converview = // Inflate Content Row
                break;
        }
    }

    switch (item.type) {
            case Header:
                //Set header row content
                break;
            case Content:
                //Set content row content
                break;
    }

    return convertView;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多