MVVMCross绑定崩溃的Andr​​oid应用 [英] MVVMCross Binding Crashes Android Application

查看:241
本文介绍了MVVMCross绑定崩溃的Andr​​oid应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Android应用程序的基础上Xamarin和MvvmCross。 在该应用程序有一个与我对我自己创建的ExpandableListView的视图。 现在,这份名单显示几个项目,这必将对使用MvvmCross自己的DataContext。 然而,由于个别ListItemViews的看法有所不同了这么多,这些ListItemViews的一部分被编程的ExpandedListViewAdapter产生。 这类似于这样:

I have an Android App based on Xamarin and MvvmCross. In that application there is a view with an ExpandableListView that I created on my own. Now this list displays several items, which are bound to their DataContext using MvvmCross. However, as the views of individual ListItemViews differs so much, part of those ListItemViews is generated programmatically in the ExpandedListViewAdapter. This works like so:

        public override View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
        {
            object child = GetRawChild(groupPosition, childPosition);

            if (child == null)
            {
                MvxBindingTrace.Trace(MvxTraceLevel.Error, "GetView called for group that seems to have no itemssource: it is null");
                return null;
            }

            var view = (MvxListItemView)GetBindableView(convertView, child, ChildItemTemplateId);
            var placeholder = view.FindViewById<BindableFrameLayout>(Resource.Id.placeholder);

            var questionVm = (QuestionViewModel)child;

            if(questionVm.ViewType == "TextBox")
            {
                    placeholder.RemoveAllViews();

                    var text = new BindableEditText(context);

                    text.InputType = InputType;
                    text.SetRawInputType(InputType);
                    placeholder.RemoveAllViews();
                    placeholder.AddView(text);

                    var answer = questionVm.Children.First();
                    text.DataContext = answer;
                    var binding = text.CreateInlineBindingTarget<AnswerViewModel>();
                    text.Bind(binding, et => et.Text, vm => vm.Model.Value, (string)null, null, null,
                              MvxBindingMode.TwoWay);
            }
            else if(questionVm.ViewType == "Spinner")
            {
                    placeholder.RemoveAllViews();

                    MvxSpinner spinner = new MvxSpinner(context, null);
                    spinner.ItemsSource = questionVm.Children;
                    spinner.ItemSelected += (sender, args) =>
                    {
                        for (int i = 0; i < questionVm.Children.Count; i++)
                        {
                            var answer = (IAnswerViewModel)questionVm.Children[i];
                            if (i == spinner.SelectedItemPosition)
                                answer.IsSelected = true;
                            else
                                answer.IsSelected = false;
                        }
                    };
                    spinner.Bind(bindings, ctrl => ctrl.ItemsSource, vm => vm.Children, (string)null, null, null, MvxBindingMode.OneWay);
                    var chosenAnswer = questionVm.Children.Cast<IAnswerViewModel>().FirstOrDefault(@a => @a.IsSelected == true);
                    if (chosenAnswer != null)
                        spinner.SetSelection(questionVm.Children.Cast<IAnswerViewModel>().ToList().IndexOf(chosenAnswer));
                    placeholder.AddView(spinner);
            }

...和BindableEditText如下所示:             使用系统;             使用Android.Content;             使用Android.Runtime;             使用Android.Views;             使用Android.Widget;             使用Android.Util;             使用Cirrious.MvvmCross.Binding.Droid.BindingContext;             使用Cirrious.MvvmCross.Binding.BindingContext;

... and "BindableEditText" looks like the following: using System; using Android.Content; using Android.Runtime; using Android.Views; using Android.Widget; using Android.Util; using Cirrious.MvvmCross.Binding.Droid.BindingContext; using Cirrious.MvvmCross.Binding.BindingContext;

        namespace iCL.Filler.Droid.Controls
        {
            public class BindableEditText : EditText, IMvxBindingContextOwner
            {
                private readonly IMvxAndroidBindingContext _bindingContext;

                public BindableEditText(Context context)
                    : base(context)
                {
                    _bindingContext = new MvxAndroidBindingContext(context, null);
                }

                public BindableEditText(Context context, IAttributeSet attributes)
                    : base(context, attributes)
                {
                    _bindingContext = new MvxAndroidBindingContext(context, null);
                }

                public BindableEditText(Context context, IAttributeSet attributes, int defStyle)
                    : base(context, attributes, defStyle)
                {
                    _bindingContext = new MvxAndroidBindingContext(context, null);
                }

                public BindableEditText(IntPtr javaReference, JniHandleOwnership transfer)
                    : base(javaReference, transfer)
                {
                }

                protected IMvxAndroidBindingContext AndroidBindingContext
                {
                    get { return _bindingContext; }
                }

                public IMvxBindingContext BindingContext
                {
                    get { return _bindingContext; }
                    set { throw new NotImplementedException("BindingContext is readonly in the radio button"); }
                }

                protected override void Dispose(bool disposing)
                {
                    if (disposing)
                    {
                        this.BindingContext.ClearAllBindings();
                    }

                    base.Dispose(disposing);
                }

                public override void SetText(Java.Lang.ICharSequence text, TextView.BufferType type)
                {
                    try
                    {
                        base.SetText(text, type);
                    }
                    catch (Exception ex)
                    {

                    }
                }

                protected View Content { get; set; }

                public object DataContext
                {
                    get { return _bindingContext.DataContext; }
                    set { _bindingContext.DataContext = value; }
                }
            }
        }

所以,我的问题是,一旦在一段时间,当我滚动和点击通过我的列表视图,我得到一个运行时的错误,如以下内容,我的应用程序崩溃,这意味着实际上它导航回previous屏幕。

So my problem is, that once in a while, when I am scrolling and clicking through my listview, I get a runtime error like the following, and my app "crashes" which means in effect that it navigates back to the previous screen.

10-29 14:04:37.140 D/dalvikvm( 5989): GC_EXPLICIT freed 751K, 11% free 11369K/12679K, paused 0ms+1ms
10-29 14:04:39.970 D/dalvikvm( 5989): GC_FOR_ALLOC freed 715K, 16% free 10692K/12679K, paused 5ms
10-29 14:04:41.831 E/mono-rt ( 5989): Stacktrace:
10-29 14:04:41.831 E/mono-rt ( 5989): 
10-29 14:04:41.831 E/mono-rt ( 5989):   at <unknown> <0xffffffff>
10-29 14:04:41.831 E/mono-rt ( 5989):   at (wrapper managed-to-native) object.wrapper_native_0xb71f1820 (intptr,intptr,intptr,intptr,Android.Runtime.JValue[]) <IL 0x00124, 0xffffffff>
10-29 14:04:41.831 E/mono-rt ( 5989):   at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (intptr,intptr,intptr,Android.Runtime.JValue[]) [0x00000] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.8.2-branch/a25a31d0/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:612
10-29 14:04:41.831 E/mono-rt ( 5989):   at Android.Widget.CompoundButton.set_Checked (bool) [0x00070] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.8.2-branch/a25a31d0/source/monodroid/src/Mono.Android/platforms/android-14/src/generated/Android.Widget.CompoundButton.cs:255
10-29 14:04:41.831 E/mono-rt ( 5989):   at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___byte (object,intptr,intptr,intptr) <IL 0x00054, 0xffffffff>
10-29 14:04:41.831 E/mono-rt ( 5989):   at <unknown> <0xffffffff>
10-29 14:04:41.831 E/mono-rt ( 5989):   at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) <IL 0x00030, 0xffffffff>
10-29 14:04:41.831 E/mono-rt ( 5989):   at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) <IL 0x0004a, 0x0016f>
10-29 14:04:41.831 E/mono-rt ( 5989):   at System.Reflection.MethodBase.Invoke (object,object[]) <IL 0x00006, 0x00048>
10-29 14:04:41.831 E/mono-rt ( 5989):   at Cirrious.MvvmCross.Binding.Bindings.Target.MvxPropertyInfoTargetBinding.SetValueImpl (object,object) <IL 0x0001a, 0x000a7>
10-29 14:04:41.831 E/mono-rt ( 5989):   at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (object) <IL 0x0008c, 0x002b1>
The program 'Mono' has exited with code 0 (0x0).

我不知道是什么问题可能是.... 莫非,一些Java的对象已经定稿,我绑定尝试打电话了吗?

I do not know what the problem could be.... Could it be, that some Java object is already finalized, and my bindings try to call it?

推荐答案

谢谢司徒,但onestly我只贴了一些code,我写我的listadapter已经变得相当复杂呢。所以,其实我已被回收,我在code创建的控件。 不过看来我找到了解决办法。 我看着我的应用程序崩溃,最近,他们都似乎因为一些有约束力的调用一个Android窗口小部件(EditText上,微调,多选等),导致本机错误的制定者。 所以,我把跟踪消息进入处置和JavaFinalize的方法和事实证明,错误总是发生后,一些JavaFinalize的电话。 因此,我所做的就是添加以下code到所有的控制,我实现了可绑定的东西。 (如BindableEditText在上面的代码段)

Thanks stuart, but onestly I only pasted some of the code I wrote as my listadapter has become quite complex yet. So actually I already was recycling the controls that I created in code. However it seems I found the solution. I watched my app crashes lately and they all seemed to be because some binding calls the setter of an android widget (EditText, Spinner, Checkbox, etc.) which resulted in a native error. So I placed trace messages into the "Dispose" and "JavaFinalize" methods and as it turns out, the error always happened after some "JavaFinalize" calls. So what I did was to add the following code to all the controls, that I implemented as a "Bindable"something. (like the BindableEditText in the snippet above)

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

这样完全没有工作!

So that totally does the job!

警告:我也有把它添加到MvxListItemView。因此,也许它应该被添加到mvvmcross来源呢?

WARNING: I also had to add this to the "MvxListItemView". So maybe it should be added to the mvvmcross sources as well?

这篇关于MVVMCross绑定崩溃的Andr​​oid应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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