【问题标题】:Exceptions while using MvxAdapter使用 MvxAdapter 时的异常
【发布时间】:2014-08-21 00:50:46
【问题描述】:

我有以下设置: 一个有 2 个标签的应用程序。在第二个选项卡上有一个绑定到 ObservableCollection 的 ListView。在第一个选项卡上,有一些控件会导致第二个选项卡的 ViewModel 重新加载 ObservableCollection。在我添加了一个自定义 MvxAdapter 之前它运行良好(多态列表项需要它)。之后每次更新后,我都会在应用程序输出中看到以下异常(请注意,列表仍会重新加载其值):

    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 

我想知道是否有人可以帮助我找出引发这些异常的原因。

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;
    }

【问题讨论】:

  • 我怀疑你已经在某个地方实现了一个 Java 接口,而没有从 Java.Lang.Object 继承,只是传入 IntPtr.Zero 是真的吗?你能显示CustomAdapter的代码吗?
  • 不,我没有实现任何 Java 接口。这是CustomAdapter的代码:gist.github.com/anonymous/124bbc41b5187447241d
  • 不确定这里发生了什么,但如果您可以制作一个可重现的示例并将其放到 GitHub 或类似的地方,我很乐意帮助调试它。
  • 我们也经常收到这些错误。
  • 这个问题有解决办法吗?

标签: android listview xamarin mvvmcross


【解决方案1】:

我认为问题是因为MvxListView 构造函数创建了一个默认的MvxAdapter。创建绑定时,默认MvxAdapter 订阅列表绑定到的集合的集合更改事件。然而,当MvxListView.Adapter 被设置为CustomAdapter 时,原来的MvxAdapter 仍然订阅了该集合。最终,原始的 MvxAdapter 会被垃圾回收,因此当集合发生变化时,处理程序会使用已处置的对象调用,结果显示异常。

我通过派生自己的MvxListView 解决了项目中的问题,该MvxListView 覆盖构造函数并返回适配器,这意味着无需在 OnCreateView 中设置它:

public class MyListView : MvxListView
{
    public MyListView(Context context, IAttributeSet attrs) :
        base(context, attrs, new CustomAdapter(context))
    {
    }
}

只需更改布局 XML 以使用此类而不是 MvxListView,异常就会停止。

【讨论】:

  • 如果您的 CusotmAdapter 继承自 MvxAdapter,这似乎不是一个选项,因为您需要 CusotmAdapter 的构造函数的附加项。
  • @Bytemaster - 事实并非如此。 MvxAdapter 有一个构造函数,它只需要一个Context 并使用MvxAndroidBindingContextHelpers.Current() 填充IMvxAndroidBindingContext(应该在绑定膨胀过程中设置)。您的CustomAdapter 构造函数应该只使用Context 调用这个基类构造函数
  • 知道了...我能够实现它并且它运行良好。请注意,这适用于 MvxListView 和 MvxGridView。谢谢。
  • 确实,这就是解决方案。使用 listview 创建的默认适配器。
【解决方案2】:

这是一个线程问题。您必须在正确的线程中引发源的属性更改。尝试将您的源代码加载到不同的项目中,然后将其分配回列表中绑定的属性。

【讨论】:

  • 这仍然发生在我身上,即使所有将项目添加到 ObservableCollection 的工作都被强制到 UI 线程上。同时集合中的项目继承自 MvxNotifyPropertyChanged 并使用 RaiseAndSetIfChanged,因此所有属性更新也应该在 UI 线程上发生。
猜你喜欢
  • 2015-04-27
  • 2017-06-03
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多