“jobject”不得IntPtr.Zero在MonoDroid设置TextView中的文本时, [英] 'jobject' must not be IntPtr.Zero when setting textview's text in MonoDroid

查看:330
本文介绍了“jobject”不得IntPtr.Zero在MonoDroid设置TextView中的文本时,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用MvvmCross与MonoDroid。

I'm using MvvmCross with MonoDroid.

在视图模型一个计时器,每分钟我称之为 RaisePropertyChanged(MinutesRemaining) - MinutesRemaining 作为一个整数,指定时间以分钟,直到当前输入端(是的,这就是所谓的UI线程!)。

In a timer in the viewmodel, every minute I call RaisePropertyChanged("MinutesRemaining") - MinutesRemaining being an integer specifying the duration in minutes until the current entry ends (and yes, this is called on the UI thread!).

MinutesRemaining 绑定到的TextView 使用MvvmCross。

MinutesRemaining is bound to a TextView using MvvmCross.

到从Xamarin的 4.9.1 更新,该应用程序将刚刚崩溃,完全与打印到跟踪任何错误消息 - 在调试的时候它现在打破正确,并给予以下错误调用的PropertyChanged 事件时:

Until the 4.10.1 update from Xamarin, the app would just crash completely with no error message printed to the trace - it's now breaking correctly when debugging and giving the below error when invoking the PropertyChanged event:

MvxBind:Error:281.24 Problem seen during binding execution for binding Text for MinutesRemaining - problem ArgumentException: 'jobject' must not be IntPtr.Zero.
Parameter name: jobject
  at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00010] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/9d03ce3e/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:499 
  at Android.Widget.TextView.set_TextFormatted (ICharSequence value) [0x00034] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/9d03ce3e/source/monodroid/src/Mono.Android/platforms/android-14/src/generated/Android.Widget.TextView.cs:1814 
  at Android.Widget.TextView.set_Text (System.String value) [0x00013] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/9d03ce3e/source/monodroid/src/Mono.Android/platforms/android-14/src/generated/Android.Widget.TextView.cs:1823 
  at Cirrious.MvvmCross.Binding.Droid.Target.MvxTextViewTextTargetBinding.SetValueImpl (System.Object target, System.Object toSet) [0x00000] in <filename unknown>:0 
  at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (System.Object value) [0x00000] in <filename unknown>:0 
  at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource (System.Object value) [0x00000] in <filename unknown>:0 

它结合正确的第一次 - 这只是对后续 RaisePropertyChanged 称出现这种情况。同样的code也适用于Windows 8和Windows Phone。

It binds correctly the first time - it's only on subsequent RaisePropertyChanged calls that this occurs. The same code also works on Windows 8 and Windows Phone.

在用于场景适配器使用JavaFinalise上述固定的(在这里发现了问题:<一href="http://stackoverflow.com/questions/19659458/mvvmcross-binding-crashes-android-application">MVVMCross绑定崩溃的Andr​​oid应用程序)。这个问题我现在已经是同样的结果,但如果在适配器的第一个观点是绑定到父视图模型中的财产(而不是项目)。

Using JavaFinalise in the adapter used for the scenario above fixed the problem (found here: MVVMCross Binding Crashes Android Application). The problem I have now is the same result, but where the first view in an adapter is bound to a property in the parent view model (not the item).

code是如下:

public class SubjectFilterAdapter : MvxAdapter {
    private EntityListFragment<TEntity, TViewModel> _owner;

    public SubjectFilterAdapter(Context context, EntityListFragment<TEntity, TViewModel> owner) : base(context, (IMvxAndroidBindingContext)owner.BindingContext) {

        _owner = owner;
    }

    protected override View GetBindableView(View convertView, object dataContext, int templateId) {
        var view = base.GetBindableView(convertView, dataContext, templateId);

        if (templateId == ItemTemplateId && GetPosition(dataContext) == 0) {
            var set = _owner.CreateBindingSet<EntityListFragment<TEntity, TViewModel>, TViewModel>();

            set.Bind(view.FindViewById<TextView>(Resource.Id.SelectedScheduleText))
                .To(x => x.SelectedScheduleText).WithClearBindingKey("SelectedScheduleTextFilterBinding");

            set.Apply();
        }

        return view;
    }

    protected override void JavaFinalize() {
        if (this.BindingContext != null)
            this.BindingContext.ClearAllBindings();
        base.JavaFinalize();
    }
}

它正常工作,开始与(为第一对夫妇的变化),但在那之后,上述异常。使用MvvmCross 3.0.14-β3

谢谢!

推荐答案

通过混合列表项/细胞结合上下文和你进入一个相当先进区父上下文。

By mixing listitem/cell binding contexts with the parent context you're entering into quite an advanced area.

要帮助试图解释/调试,你需要了解一些有关的所有父的生命周期中,列表项/细胞的生命周期和相应的MvvmCross结合上下文的生命周期的你是怎么回事。

To help try to explain/debug what you is going on, you need to understand a little about all of the the parent lifecycle, the listitem/cell lifecycle and the lifecycles of the corresponding MvvmCross binding contexts.

在父母的生命周期的水平,这通常是一个Android 活动片段。为简单起见,我将只使用活动此答案的其余部分。

At the parent lifecycle level, this is generally an Android Activity or Fragment. For the sake of simplicity I'll just use Activity for the rest of this answer.

活动有几个关键生命周期事件

This Activity has a couple of key lifecycle events

  • 的OnCreate 被调用一次,只有当活动首次启动
  • 的OnDestroy 被调用一次,只有当活动将不再显示。
  • OnCreate is called once only when the Activity is first launched
  • OnDestroy is called once only when the Activity will not be shown again.

MvvmCross截获这些事件和:

MvvmCross intercepts these events and:

  • 的OnCreate ,它设置了一个视图模型活动的DataContext 。用户code - 正常的Xml code在的setContentView 膨胀 - 再创建绑定。这些绑定存储在的BindingContext 活动的
  • 的OnDestroy ,MvvmCross破坏内的所有绑定的BindingContext
  • within OnCreate, it sets a ViewModel as the Activity's DataContext. User code - normally Xml code inflated within SetContentView - then creates bindings. These bindings are stored within the BindingContext of the Activity
  • within OnDestroy, MvvmCross destroys all the bindings within that BindingContext

在用户界面中,我们有兴趣在这里,活动拥有的ListView ,而的ListView 有一个适配器设置它。在这种情况下,的DataContext 的ListView 适配器是相同的它的父

In the user interface we're interested in here, the Activity owns a ListView, and that ListView has an Adapter set for it. Within this scenario, the DataContext for the ListView and its Adapter is the same as it's parent.

的ListView的寿命清单可能需要出示大量物品。在任何时候显示的内容可能会发生变化 - 用户的触摸操作以及一方面是因为由于视图模型的变化。为了显示这些项目中,的ListView 询问适配器查看秒。对于每一个项目它显示了适配器提供了一个查看,这些查看之间可以重复使用(使用 convertView 参数)。但是,有时,这些查看,则也不能重复使用 - 在这种情况下,有时可以在视图,甚至在Java / Dalvik的<$后,在C#中居住对象C $ C>查看已被删除和Java完成。

Within the lifetime of the ListView the list may need to show lots of items. The items shown at any time may change - both because of user touch actions and because of view model changes. To display these items, the ListView asks the Adapter for Views. For each item it shows the Adapter supplies a View, and these Views may be reused (using the convertView parameter). However, sometimes, these Views are also not reused - and in this situation it is sometimes possible for the View object to live on in C# even after the Java/Dalvik View has been removed and Java finalized.

MvvmCross拦截 GetView 中的 MvxAdapter 调用。对于每个调用返回不只是一个查看,但此外和 MvxListItemView 。这是一个查看与添加的BindingContext - 这可以让MvvmCross用户绑定每个 MvxListItemView 其项目的DataContext

MvvmCross intercepts the GetView calls within its MvxAdapter. For each call it returns not just a View but moreover and MvxListItemView. This is a View with an added BindingContext - and this allows MvvmCross users to bind each MvxListItemView to its list item DataContext.

MvxListItemView 可重复使用,它是简单的MvvmCross简单地改变其的DataContext

When a MvxListItemView is reused, it's simple for MvvmCross to simply change its DataContext.

MvxListItemView 不重复使用 - 当它从用户界面中删除,然后 JavaFinalize D - MvvmCross拦截在 OnDetachedFromWindow 事件,并使用它来切换的DataContext 。它这样做是对 OnDetachedFromWindow ,而不是 JavaFinalize 作为窗口调用是保证在UI线程,并因为它使感觉(我)像一个清洁的地方做到这一点。

When a MvxListItemView is not reused - when it is removed from the UI and then JavaFinalized - MvvmCross intercepts the OnDetachedFromWindow event and it uses this to switch the DataContext to null. It does this on OnDetachedFromWindow rather than JavaFinalize as the Window call is guaranteed to be made on the UI thread and as it feels (to me) like a cleaner place to do this.

注意的一些这种行为已经潜移默化地改变了在最近的版本 - 但高于此的描述是正确的v3.0.14

Note that some of this behaviour has subtly changed in recent releases - but this description above is correct for v3.0.14

通过这种背景下的地方,它出现什么您正在试图做的是建立一个绑定的内容 ListItemView 的BindingContext 活动的

With that background in place, what it appears you are currently trying to do is to create a binding for the contents of a ListItemView within the BindingContext of the Activity.

这意味着绑定并不真正具备的 ListItemView 的生命周期有很好的理解 - 这样的结合可以说活着即使在 ListItemView 已经从屏幕上被删除,(可能)完成。

This means that the binding doesn't really have a good understanding of the lifecycle of the ListItemView - so the binding can say alive even after the ListItemView has been removed from the screen and (maybe) finalized.

要解决这个问题...

To resolve this issue...

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆