I have the following setup: An app with 2 tabs. On the second tab there is a ListView bound to an ObservableCollection. On the first tab there are controls that cause a ViewModel for the second tab to reload the ObservableCollection. It worked well until I added a custom MvxAdapter (need it for polymorphic list items). After that after each update I see the following exceptions in the application output (note that the list still reloads its values):
mvx:Warning: 42.24 Exception masked during Adapter RealNotifyDataSetChanged ArgumentException: 'jobject' must not be IntPtr.Zero.
Parameter name: jobject
at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (IntPtr jobject, IntPtr jclass, IntPtr jmethod) [0x00010] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.14-series/8e79d361/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:866
at Android.Widget.BaseAdapter.NotifyDataSetChanged () [0x00058] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.14-series/8e79d361/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.Widget.BaseAdapter.cs:311
at Cirrious.MvvmCross.Binding.Droid.Views.MvxAdapter.RealNotifyDataSetChanged () [0x00000] in <filename unknown>:0
mvx:Warning: 42.24 Exception masked during Adapter RealNotifyDataSetChanged ArgumentException: 'jobject' must not be IntPtr.Zero.
Parameter name: jobject
at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (IntPtr jobject, IntPtr jclass, IntPtr jmethod) [0x00010] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.14-series/8e79d361/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:866
at Android.Widget.BaseAdapter.NotifyDataSetChanged () [0x00058] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.14-series/8e79d361/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.Widget.BaseAdapter.cs:311
at Cirrious.MvvmCross.Binding.Droid.Views.MvxAdapter.RealNotifyDataSetChanged () [0x00000] in <filename unknown>:0
I wonder if someone can help me to find the reason why these exceptions are thrown.
public override View OnCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.ChildPage_History, null);
listView = view.FindViewById<MvxListView> (Resource.Id.history_list);
listView.Adapter = new CustomAdapter (this.Activity, (IMvxAndroidBindingContext)BindingContext);
return view;
}
I think the problem is caused because the MvxListView constructor creates a default MvxAdapter. When the bindings are created the default MvxAdapter subscribes to the collection changed event for the collection the list is bound to. However, when the MvxListView.Adapter is then set to the CustomAdapter, the original MvxAdapter is still subscribed to the collection as well. Eventualy the original MvxAdapter gets garbage collected so when the collection changes the handler is called with a disposed object and the exception shown is the result.
I solved the problem in my project by deriving my own MvxListView that overrides the constructor and returns the adapter, meaning there's no need to set it in OnCreateView:
public class MyListView : MvxListView
{
public MyListView(Context context, IAttributeSet attrs) :
base(context, attrs, new CustomAdapter(context))
{
}
}
Just change the layout XML to use this class instead of MvxListView and the exceptions should stop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With