xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.64k stars 1.88k forks source link

'Index was out of range.' on CarouselView #14237

Open rumbledot opened 3 years ago

rumbledot commented 3 years ago

Description

Hi, I'm not sure what this is. I've tried to debug it as best as I can as my experience is pretty limited. I'm hoping to learn something from this experience.

CarouselView display items correctly on first load. After navigate to different page and back to the said page. Application in debug mode stops and throws :

[RecyclerView] Cannot scroll to position a LayoutManager set. Call setLayoutManager with a non-null argument.

and

System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index'
In android device, application stop unexpectedly.

I don't have any function that call CarouselView scroll to position. I've put try catch in all suspected functions but no error was caught. Application successfully built and deployed.

Steps to Reproduce

  1. Opening the application will load 'Today's Job' page
  2. Navigate to different page 'Week in review'
  3. Navigate back to 'Today's Job'
  4. Application throws the above error in Debug mode or exit unexpectedly on device

Expected Behavior

Navigate back and forth without error.

Actual Behavior

Application exit unexpectedly when run on Android device.

Basic Information

Environment

you can find 'Output-Debug.txt' in the repository

Screenshots

Reproduction Link

https://github.com/rumbledot/T_Rec_Public.git

Workaround

manually set CarouselView.Position = 1 when a flag of items loaded is set to true

jsuarezruiz commented 3 years ago
[com.fabe.t_rec] runtime.cc:663] JNI DETECTED ERROR IN APPLICATION: JNI CallStaticObjectMethodA called with pending exception android.runtime.JavaProxyThrowable: System.ObjectDisposedException: Cannot access a disposed object.
[com.fabe.t_rec] runtime.cc:663] Object name: 'Xamarin.Forms.Platform.Android.CarouselViewRenderer'.
[com.fabe.t_rec] runtime.cc:663]   at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <ca58f549573145d1b1fc6ea9f18f6ea3>:0 
[com.fabe.t_rec] runtime.cc:663]   at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <ca58f549573145d1b1fc6ea9f18f6ea3>:0 
[com.fabe.t_rec] runtime.cc:663]   at AndroidX.RecyclerView.Widget.RecyclerView.GetAdapter () [0x00000] in D:\a\1\s\generated\androidx.recyclerview.recyclerview\obj\Release\monoandroid90\generated\src\AndroidX.RecyclerView.Widget.RecyclerView.cs:12865 
[com.fabe.t_rec] runtime.cc:663]   at Xamarin.Forms.Platform.Android.ItemsViewRenderer`3[TItemsView,TAdapter,TItemsViewSource].UpdateEmptyViewVisibility () [0x0007c] in D:\a\1\s\Xamarin.Forms.Platform.Android\CollectionView\ItemsViewRenderer.cs:650 
[com.fabe.t_rec] runtime.cc:663]   at Xamarin.Forms.Platform.Android.DataChangeObserver.OnChanged () [0x00006] in D:\a\1\s\Xamarin.Forms.Platform.Android\CollectionView\DataChangeObserver.cs:47 
[com.fabe.t_rec] runtime.cc:663]   at AndroidX.RecyclerView.Widget.RecyclerView+AdapterDataObserver.n_OnChanged (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in D:\a\1\s\generated\androidx.recyclerview.recyclerview\obj\Release\monoandroid90\generated\src\AndroidX.RecyclerView.Widget.RecyclerView.cs:843 
[com.fabe.t_rec] runtime.cc:663]   at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.104(intptr,intptr)
[com.fabe.t_rec] runtime.cc:663]   at void crc643f46942d9dd1fff9.DataChangeObserver.n_onChanged() (DataChangeObserver.java:-2)
[com.fabe.t_rec] runtime.cc:663]   at void crc643f46942d9dd1fff9.DataChangeObserver.onChanged() (DataChangeObserver.java:34)
[com.fabe.t_rec] runtime.cc:663]   at void androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged() (RecyclerView.java:12253)
[com.fabe.t_rec] runtime.cc:663]   at void androidx.recyclerview.widget.RecyclerView$Adapter.notifyDataSetChanged() (RecyclerView.java:7354)
[com.fabe.t_rec] runtime.cc:663]   at void mono.android.view.View_OnClickListenerImplementor.n_onClick(android.view.View) (View_OnClickListenerImplementor.java:-2)
[com.fabe.t_rec] runtime.cc:663]   at void mono.android.view.View_OnClickListenerImplementor.onClick(android.view.View) (View_OnClickListenerImplementor.java:30)
[com.fabe.t_rec] runtime.cc:663]   at boolean android.view.View.performClick() (View.java:7448)
[com.fabe.t_rec] runtime.cc:663]   at boolean android.view.View.performClickInternal() (View.java:7425)
[com.fabe.t_rec] runtime.cc:663]   at boolean android.view.View.access$3600(android.view.View) (View.java:810)
[com.fabe.t_rec] runtime.cc:663]   at void android.view.View$PerformClick.run() (View.java:28305)
[com.fabe.t_rec] runtime.cc:663]   at void android.os.Handler.handleCallback(android.os.Message) (Handler.java:938)
[com.fabe.t_rec] runtime.cc:663]   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:99)
[com.fabe.t_rec] runtime.cc:663]   at void android.os.Looper.loop() (Looper.java:223)
[com.fabe.t_rec] runtime.cc:663]   at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:7656)
[com.fabe.t_rec] runtime.cc:663]   at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
[com.fabe.t_rec] runtime.cc:663]   at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:592)
[com.fabe.t_rec] runtime.cc:663]   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:947)
angelru commented 3 years ago

something like that https://github.com/xamarin/Xamarin.Forms/issues/13991

rumbledot commented 3 years ago

I don't use jump to CarouselView position. As a workaround, I did set the position to 1 if it is not empty. That causing another problem, when there is only one item loaded to CarouselView. And most of the time it still throwing index out of range issue. It seemed, CarouselView re-organize itself after the code feeds it data. Reset it self to first position and looking for one position behind the set position. I'm guessing it was trying to display peek before item?

I also learned that previous page and its viewmodel get disposed when navigating to another page. (Which is good) I got 'can't access disposed' variable exception when navigating back.