【问题标题】:Android ListView array index out of bounds after filter过滤后Android ListView数组索引超出范围
【发布时间】:2013-02-12 20:12:08
【问题描述】:

我认为这是专家的问题。

我收到来自 ListView 数据列表的 位置 超出范围 的对 getView() 的调用。
当我使用适配器过滤器时会发生这种情况。过滤器publishResults() 方法使用小于原始列表的过滤列表填充数据。
当新的过滤列表比以前的过滤列表短时,似乎会发生错误。 我将getView() 的代码更改为在越界时返回一个虚拟convertView,只是为了查看发出了多少这样的调用。

这些是相关代码和我记录的log 消息:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // No logs here to keep ListView performance good
        Log.d(TAG, "+ getView( position=" + position + ")");
        ViewHolder holder;

        if( position >= mData.size() ) {
            // This code allows to see how many bad calls I get
            Log.w(TAG, "position out of bounds!");
            convertView = mInflater.inflate(mLayout, parent, false);
            return convertView;
        }

        . . . // Normal getView code

        return convertView;
    }

在过滤器中(代码复制自ArrayAdapter源代码)

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            Log.pe(TAG, "+ publishResults(constraint:" + constraint + ", results.count:" + results.count + ")");
            //noinspection unchecked
            mData = (ArrayList<String>) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
            Log.px(TAG, "- publishResults()");
        }

日志文件显示,经过 7 个结果的过滤器后,出现了一个具有 3 个结果的 fitler,但 getView 不断收到 7 个项目的调用(我用*** 标记了越界调用):

02-26 05:31:55.986: D/ViewerActivity(22857): + onQueryTextChange(newText:log)
02-26 05:31:55.986: D/ViewerActivity(22857): - onQueryTextChange()
02-26 05:31:56.029: D/LogScreenAdapter(22857): + performFiltering(prefix:log)
02-26 05:31:56.113: D/dalvikvm(22857): GC_CONCURRENT freed 378K, 5% free 13577K/14215K, paused 0ms+1ms
02-26 05:31:56.153: D/LogScreenAdapter(22857): - performFiltering()
02-26 05:31:56.153: D/LogScreenAdapter(22857): + publishResults(constraint:log, results.count:7)
02-26 05:31:56.167: D/LogScreenAdapter(22857): - publishResults()
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=1)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=2)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=3)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=4)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=5)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=6)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=1)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=2)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=3)
02-26 05:31:56.167: D/LogScreenAdapter(22857): + getView( position=4)
02-26 05:31:56.493: D/LogScreenAdapter(22857): + getView( position=5)
02-26 05:31:56.503: D/LogScreenAdapter(22857): + getView( position=6)
02-26 05:32:23.793: D/ViewerActivity(22857): + onQueryTextChange(newText:logs)
02-26 05:32:23.793: D/ViewerActivity(22857): - onQueryTextChange()
02-26 05:32:23.813: D/LogScreenAdapter(22857): + performFiltering(prefix:logs)
02-26 05:32:23.854: D/dalvikvm(22857): GC_CONCURRENT freed 383K, 5% free 13577K/14215K, paused 0ms+0ms
02-26 05:32:23.924: D/dalvikvm(22857): GC_CONCURRENT freed 388K, 5% free 13573K/14215K, paused 0ms+1ms
02-26 05:32:23.974: D/LogScreenAdapter(22857): - performFiltering()
02-26 05:32:23.983: D/LogScreenAdapter(22857): + publishResults(constraint:logs, results.count:3)
02-26 05:32:23.983: D/LogScreenAdapter(22857): - publishResults()
02-26 05:32:23.983: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:32:24.074: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:32:24.093: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:32:24.113: D/LogScreenAdapter(22857): + getView( position=1)
02-26 05:32:24.155: D/LogScreenAdapter(22857): + getView( position=2)
02-26 05:32:24.164: D/LogScreenAdapter(22857): + getView( position=3)
*** 02-26 05:32:24.193: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.233: D/LogScreenAdapter(22857): + getView( position=4)
*** 02-26 05:32:24.263: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.284: D/LogScreenAdapter(22857): + getView( position=5)
*** 02-26 05:32:24.313: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.333: D/LogScreenAdapter(22857): + getView( position=6)
*** 02-26 05:32:24.343: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.353: D/LogScreenAdapter(22857): + getView( position=0)
02-26 05:32:24.373: D/LogScreenAdapter(22857): + getView( position=1)
02-26 05:32:24.383: D/LogScreenAdapter(22857): + getView( position=2)
02-26 05:32:24.403: D/LogScreenAdapter(22857): + getView( position=3)
*** 02-26 05:32:24.413: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.433: D/LogScreenAdapter(22857): + getView( position=4)
*** 02-26 05:32:24.443: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.463: D/LogScreenAdapter(22857): + getView( position=5)
*** 02-26 05:32:24.475: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:32:24.483: D/LogScreenAdapter(22857): + getView( position=6)
*** 02-26 05:32:24.503: W/LogScreenAdapter(22857): position out of bounds!
02-26 05:38:26.769: D/dalvikvm(22857): GC_CONCURRENT freed 316K, 5% free 13640K/14215K, paused 0ms+1ms

您在这里看到的是,publishResults() 方法确实将 mData 从 7 项列表更改为更短的 3 项列表,请参见上面的代码,但 Adapter 不断收到 getView() 对 7 项的调用项目列表,即使它不再存在。
请注意,notifyDataSetChanged() 已通过新的数据分配调用,因此 ListView 应该知道新列表。

【问题讨论】:

  • 是否调用了 getItemCount 函数,如果调用了,它返回了什么?如果您正在覆盖它,请发布代码。
  • getItemCount 返回什么?
  • 我不会覆盖 getItemCount,应该这样吗?
  • 我认为这是专家的问题。好笑!
  • @RobinHood 那只意味着我不是专家。很高兴我能让你微笑。我更改了代码,到目前为止我没有越界。如果有人愿意发布答案,我会将其标记为已回答。

标签: android listview filter android-arrayadapter


【解决方案1】:

您在自定义列表视图适配器的public int getCount() 方法中返回了什么?

你应该像mData != null? mData.size() : 0一样返回,

由于可能是您返回的列表大小超过了要在列表中显示的数据

getCount() 自定义列表适配器的方法指定列表视图的大小,因此它应该是您在列表中传递的数据的大小

【讨论】:

  • 你拯救了我的一天!我完全忘了覆盖getCountmethod
【解决方案2】:

似乎重写“getCount()”方法可以解决您的问题:

@Override
public int getCount() {
    return mData.size();
}

【讨论】:

  • 非常感谢...为此 +1
  • 此语句存在但同样的问题
【解决方案3】:

我这样做了,它解决了我的问题

@Override
public int getCount() {

    if (isFiltered == true) {
        return myFilteredArray.size();
    }

    return myUnfilteredArray.size();
} 

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多