Valeriy Kovalenko
Valeriy Kovalenko

Reputation: 165

Exceptions while using MvxAdapter

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

Answers (2)

Graham Pett
Graham Pett

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

1lb3r
1lb3r

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

Related Questions