Reputation: 165
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;
}
Upvotes: 3
Views: 626
Reputation: 123
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.
Upvotes: 5
Reputation: 508
This is a threading problem. You have to raise the property change of the source in the correct thread. Try to load your source in a different project and then assign it back to the property binded in the list.
Upvotes: 1