【问题标题】:Accesing the first element of an updated listview causes System.ArgumentOutOfRangeException访问更新列表视图的第一个元素会导致 System.ArgumentOutOfRangeException
【发布时间】:2019-07-20 10:25:03
【问题描述】:

我更新列表,从中删除不需要的项目,然后调用 adapter.NotifyDataSetChanged。当我单击更新后的 ListView 中的第一个元素时,System.ArgumentOutOfRangeException 会弹出(这个元素似乎保留了它在更新之前在列表中的索引 )。相反,当我单击更新后的列表视图中的其他项目时,没有问题。

List<Event> eventsToRemove = new List<Events>;

//Populating eventsToRemove with some "not-matching-some-criterion" <Event> instances taken from the original List<Event> events

for (var i = 0; i < eventsToRemove.Count; i++) {
                        events.Remove(eventsToRemove[i]);
}
adapter.NotifyDataSetChanged();

我猜问题出在更新适配器的线程和管理 UI 的线程上。我想解决这个问题:

Unhandled Exception:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

Parameter name: index

日志:

07-20 12:54:41.252 D/ViewRootImpl@3e1ee4d[Toast](18915): MSG_RESIZED_REPORT: ci=Rect(0, 0 - 0, 0) vi=Rect(0, 0 - 0, 0) or=1
07-20 12:54:41.667 D/ViewRootImpl@3e1ee4d[Toast](18915): mHardwareRenderer.destroy()#4
07-20 12:54:41.667 D/ViewRootImpl@5f20f01[MainActivity](18915): ViewPostImeInputStage processPointer 0
07-20 12:54:41.668 D/ViewRootImpl@3e1ee4d[Toast](18915): dispatchDetachedFromWindow
07-20 12:54:41.674 D/InputTransport(18915): Input channel destroyed: fd=75
07-20 12:54:41.716 D/ViewRootImpl@5f20f01[MainActivity](18915): ViewPostImeInputStage processPointer 1
07-20 12:54:42.057 D/Mono    (18915): Assembly Ref addref Mono.Android[0x73a4bea880] -> System.Runtime.Serialization[0x738f4cf780]: 3
Unhandled Exception:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

Thread finished: <Thread Pool> #10
Il thread 0xa è terminato con il codice 0 (0x0).
Thread finished: <Thread Pool> #5
Il thread 0x5 è terminato con il codice 0 (0x0).
Thread finished: <Thread Pool> #12
Il thread 0xc è terminato con il codice 0 (0x0).
Thread finished: <Thread Pool> #6
Il thread 0x6 è terminato con il codice 0 (0x0).
Thread finished: <Thread Pool> #11
Il thread 0xb è terminato con il codice 0 (0x0).

Github 链接及相应代码:https://github.com/eddybudge/PerugiaEventi1/blob/master/PerugiaEventi1/MainActivity.cs

另外,当我点击更新列表的第一个元素时,我会在控制台上得到以下输出:

[0:] Position: 0 Number of elements inside the list: 9
[0:] Position: 1 Number of elements inside the list: 9
[0:] Position: 2 Number of elements inside the list: 9
[0:] Position: 3 Number of elements inside the list: 9
[0:] Position: 4 Number of elements inside the list: 9
[0:] Position: 5 Number of elements inside the list: 9
[0:] Position: 6 Number of elements inside the list: 9
[0:] Position: 7 Number of elements inside the list: 9
[0:] Position: 8 Number of elements inside the list: 9
[0:] Position: 9 Number of elements inside the list: 9

,而 当我点击任何其他按钮时,我会得到

[0:] Position: x Number of elements inside the list: y
  • 这很奇怪,因为应该只打印一行!!!

(我每次点击按钮时都使用System.Diagnostics.Debug.WriteLine("Position: "+position+" Number of elements inside the list: "+eventi.Count());)

更新:

最后我决定捕获异常并使用内部捕获0作为索引 - 因为在测试期间它始终是导致问题的第一个元素。 顺便说一句,我没有找到问题的核心 - 这就是造成问题的原因和原因。

【问题讨论】:

  • 可以添加错误日志吗?
  • 已添加!应该够了吧?
  • 什么是events?你能添加完整的相关代码吗?
  • 我提供了带有代码的github链接,可以吗? events 是 List&lt;Event&gt;,其中 Event 是 POJO
  • for (var i = 0; i

标签: android listview user-interface xamarin adapter


【解决方案1】:

关于这个问题

此外,当我单击更新列表的第一个元素时,我会得到 控制台上的以下输出

[0:] Position: 0 Number of elements inside the list: 9
[0:] Position: 1 Number of elements inside the list: 9
[0:] Position: 2 Number of elements inside the list: 9
[0:] Position: 3 Number of elements inside the list: 9
[0:] Position: 4 Number of elements inside the list: 9
[0:] Position: 5 Number of elements inside the list: 9
[0:] Position: 6 Number of elements inside the list: 9
[0:] Position: 7 Number of elements inside the list: 9
[0:] Position: 8 Number of elements inside the list: 9
[0:] Position: 9 Number of elements inside the list: 9

你只需要添加以下代码

 if (!bottoneEvento.HasOnClickListeners) {
 }

如下:

public override View GetView(int position, View convertView, ViewGroup parent)
    {
        var view = convertView ?? activity.LayoutInflater.Inflate(Resource.Layout.list_item, parent, false);
        var bottoneEvento = view.FindViewById<Button>(Resource.Id.bottoneEventAdapter);

        bottoneEvento.Text = eventi[position].Titolo;
        //bottoneEvento.Tag = position;  --forse non serve
        if (!bottoneEvento.HasOnClickListeners)  // key code
        {
            bottoneEvento.Click += (sender, args) =>
          {
            System.Diagnostics.Debug.WriteLine("Position: "+position+" Number of elements inside the list: "+eventi.Count());
            //bisogna, immagino fare l'update della view con notify - prima creando un observer.
            Intent dettagli = new Intent(Application.Context, typeof(EventoInDettaglio));
            dettagli.PutExtra("titolo", bottoneEvento.Text);
            dettagli.PutExtra("url", eventi[position].Url);
            dettagli.PutExtra("inizia", eventi[position].Inizio);
            dettagli.PutExtra("finisce", eventi[position].Fine);
            dettagli.PutExtra("descrizione", eventi[position].Descrizione);
            Application.Context.StartActivity(dettagli);
          };
        }

        return view;
    }

注意:我无法重现您上面所说的第一个问题。

【讨论】:

  • 感谢您的建议,但这个想法似乎效果不佳,因为有时我访问事件的标题和它们的 url 不匹配。我决定尝试异常处理,因此它是基于经验问题案例的硬编码解决方案。我有点修补了这个问题,但顺便说一下没有得到它的原因......
  • 添加判断代码时(if (!bottoneEvento.HasOnClickListeners) {//...}),第二个错误依然存在?但在我的测试中效果很好。
  • 第二个错误不存在,但弹出另一个逻辑错误-它使事件的标题和其他字段不匹配。这对我来说不是一个解决方案。
  • 能否详细说明您的问题?
  • 我的意思是`它使事件的标题和其他字段不匹配`的错误到底是什么。
【解决方案2】:

您删除单个 for 循环中的所有项目..发送位置以删除事件

img_remove.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            if(eventsToRemove.size() > 0)
              events.Remove(eventsToRemove[position])
        }
    });

【讨论】:

  • 实际上并非如此——我不会在循环的单次迭代中删除所有项目
  • 删除循环中的所有项目
  • 请放置一个日志,一次打印 i 值和数组列表的大小..每次..你会清楚项目位置是否存在
  • 按照你的要求做了 - 每次单击按钮时,都会在日志中添加一行,其中包含按钮的索引和列表的大小。
  • 至于您的代码示例,当我单击它们时,我不会消除按钮 - 当它们代表的事件不符合某些标准时,我会消除按钮 - 也就是说它们不会在我选择的日期发生使用 DatePicker。
猜你喜欢
  • 2021-12-06
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多