You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ListView访问列表最后一项时触发NullReferenceException异常

问题根因

你遇到的空引用和数据源是否为空没有任何关系,核心是混淆了ListView的两个完全不同的索引逻辑:

  • lstViewData.Count实际取的是适配器绑定的全量数据总条数,你这里5条数据取值0-4本身没错
  • 但lstViewData.GetChildAt(i)获取的是 ListView当前屏幕上挂载的可见子View实例,这个方法的入参不是数据源的全局位置索引,而是可见区域内子View的相对索引,取值范围只能是0到lstViewData.ChildCount - 1。

ListView本身做了View复用优化,不在当前可见区域的列表项根本不会生成对应的View实例挂载到控件上,哪怕对应位置的数据源有值,调用GetChildAt传入对应全局索引也会返回null,自然触发空引用异常。哪怕你的5条数据刚好一屏能放下,只要列表发生过滚动,可见子View的相对索引和数据源全局索引就会出现错位,直接传遍历的i值本身就是错误用法。

临时修复方案(仅解决空引用,仍有复用隐患)

不要用全量数据长度做遍历边界,只遍历当前实际存在的可见子View,同时通过View反查对应的真实数据源位置再设置背景,你的事件绑定代码lstViewData.ItemClick += OnListViewItemClicked;不需要修改,只需要替换点击事件实现即可:

private void OnListViewItemClicked(object sender, AdapterView.ItemClickEventArgs e)
{
    int selectedPos = e.Position;
    // 用ChildCount做遍历边界,只处理实际存在的子View
    for (int i = 0; i < lstViewData.ChildCount; i++)
    {
        View itemView = lstViewData.GetChildAt(i);
        // 反查当前子View对应的真实数据源位置
        int realPos = lstViewData.GetPositionForView(itemView);
        itemView.SetBackgroundColor(realPos == selectedPos 
            ? Android.Graphics.Color.Gray 
            : Android.Graphics.Color.Transparent);
    }
}
规范实现方案(适配复用机制,无状态错乱)

直接操作子View改背景的写法不符合ListView的设计逻辑,列表滑动后View复用时会出现高亮位置错乱的问题,正确实现选中高亮的方式是把选中状态存在适配器层:

  1. 在你的自定义适配器里增加一个公开的选中位置字段,默认值设为-1(无选中)
  2. 在适配器的GetView方法中,根据当前渲染项的position和选中位置字段的匹配关系,设置对应背景色
  3. 点击事件中只需要更新适配器的选中位置字段,调用NotifyDataSetChanged()触发列表刷新即可,不需要手动遍历修改子View。

内容的提问来源于stack exchange,提问作者Josip Juros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 17:24:21