Android Fragment Dispose导致崩溃(有时)

时间:2015-02-11 23:38:26

标签: c# android xamarin xamarin.android mvvmcross

我有一个MvxDialogFragment(Mvvmcross),当它关闭时,有时会导致致命错误。

班级:

namespace Keiser.IPS.Screen.Droid.Views
{
    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Widget;
    using Cirrious.MvvmCross.Binding.Droid.BindingContext;
    using Cirrious.MvvmCross.Binding.Droid.Views;
    using Cirrious.MvvmCross.Droid.Fragging.Fragments;
    using Keiser.IPS.Screen.Core.ViewModels;
    using System;

    public class SettingsView : MvxDialogFragment
    {
        protected Android.Views.View InflatedView;

        public bool IsOpen { get; protected set; }

        public override Dialog OnCreateDialog(Bundle savedState)
        {
            base.EnsureBindingContextSet(savedState);
            IsOpen = true;

            SettingsViewModel.SystemSettingsEvent += GoToSystemSettings;
            SettingsViewModel.OnUpdateEvent += DoingUpdate;

            InflatedView = this.BindingInflate(Resource.Layout.SettingsView, null);
            CheckDemoSection();
            CheckLicenseSection();
            CheckUpdateSection();

            MvxSpinner languageSpinner = InflatedView.FindViewById<MvxSpinner>(Resource.Id.LanguageSpinner);
            languageSpinner.Focusable = true;
            languageSpinner.FocusableInTouchMode = true;

            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(Activity, Resource.Style.Theme_Dialog);
            alertDialogBuilder.SetTitle(SettingsViewModel.GetText("GeneralSettings"));
            alertDialogBuilder.SetView(InflatedView);
            alertDialogBuilder.SetNegativeButton(SettingsViewModel.GetText("Cancel"), delegate { Cancel(); });
            alertDialogBuilder.SetPositiveButton(SettingsViewModel.GetText("Save"), delegate { Save(); });
            return alertDialogBuilder.Create();
        }

        protected SettingsViewModel SettingsViewModel { get { return ViewModel as SettingsViewModel; } }

        protected void Save()
        {
            SettingsViewModel.SaveSettings();
            IsOpen = false;
        }

        protected void Cancel()
        {
            IsOpen = false;
        }

        public override void OnCancel(IDialogInterface dialog)
        {
            base.OnCancel(dialog);
            Cancel();
        }

        protected void CheckLicenseSection()
        {
            if (!SettingsViewModel.ShowLicenseSection)
                InflatedView.FindViewById<LinearLayout>(Resource.Id.SettingsContainer).RemoveView(InflatedView.FindViewById<LinearLayout>(Resource.Id.LicenseContainer));
        }

        protected void CheckDemoSection()
        {
            if (!SettingsViewModel.ShowDemoSection)
                InflatedView.FindViewById<LinearLayout>(Resource.Id.SettingsContainer).RemoveView(InflatedView.FindViewById<TextView>(Resource.Id.DemoModeLabel));
            else
                InflatedView.FindViewById<TextView>(Resource.Id.DemoModeLabel).Text += ": " + SettingsViewModel.GetText("On");
        }

        protected void CheckUpdateSection()
        {
            if (!SettingsViewModel.SoftwareManagerService.SoftwareManager.UpdateAvailable)
                InflatedView.FindViewById<LinearLayout>(Resource.Id.SettingsContainer).RemoveView(InflatedView.FindViewById<LinearLayout>(Resource.Id.UpdateContainer));
        }

        protected void GoToSystemSettings(object s, EventArgs e)
        {
            StartActivityForResult(new Intent(Android.Provider.Settings.ActionSettings, null), 0);
        }

        protected void DoingUpdate(object s, EventArgs e)
        {
            new AlertDialog.Builder(Activity).SetMessage(SettingsViewModel.GetText("UpdatingMessage")).Show();
        }

    }
}

查看被强制执行:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="5dp"
        android:id="@+id/SettingsContainer">
        <TextView
            local:MvxLang="Text Language"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <Mvx.MvxSpinner
            android:layout_width="match_parent"
            android:layout_height="?android:attr/listPreferredItemHeight"
            local:MvxBind="ItemsSource Languages; SelectedItem Language"
            android:id="@+id/LanguageSpinner" />
        <TextView
            local:MvxLang="Text Theme"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <Mvx.MvxSpinner
            android:layout_width="match_parent"
            android:layout_height="?android:attr/listPreferredItemHeight"
            local:MvxBind="ItemsSource Themes; SelectedItem Theme"
            android:id="@+id/ThemeSpinner" />
        <TextView
            local:MvxLang="Text Legend"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <Switch
            local:MvxBind="Checked Legend"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="6dp"
            android:layout_marginBottom="11dp"
            local:MvxLang="TextOn On; TextOff Off" />
        <TextView
            local:MvxLang="Text DemoMode"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="20dp"
            android:id="@+id/DemoModeLabel" />
        <TextView
            local:MvxBind="Text SoftwareCode"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="20dp"
            android:id="@+id/CodeLabel" />
        <TextView
            local:MvxBind="Text SoftwareVersion"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="20dp"
            android:id="@+id/VersionLabel" />
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="20dp"
            android:id="@+id/LicenseContainer">
            <TextView
                local:MvxLang="Text LicenseKey"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/LicenseKeyLabel" />
            <EditText
                local:MvxBind="Text LicenseKey; TextColor LicenseKeyColor"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:maxLines="1" />
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="10dp"
            android:id="@+id/SystemSettingsContainer">
            <Button
                local:MvxLang="Text SystemSettings"
                local:MvxBind="Click GoToSystemSettings"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="10dp"
            android:id="@+id/UpdateContainer">
            <Button
                local:MvxLang="Text Update"
                local:MvxBind="Click DoUpdateCommand; Enabled CanDoUpdate"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

堆栈跟踪:

02-12 07:14:52.504: E/mono-rt(21076): [ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: 'jobject' must not be IntPtr.Zero.
02-12 07:14:52.504: E/mono-rt(21076): Parameter name: jobject
02-12 07:14:52.504: E/mono-rt(21076):   at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Android.Views.View.SetOnClickListener (IOnClickListener l) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Android.Views.View+<>c__AnonStorey7.<>m__0 (IOnClickListener __v) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Java.Interop.EventHelper.RemoveEventHandler[IOnClickListener,IOnClickListenerImplementor] (System.WeakReference& implementor, System.Func`2 empty, System.Action`1 unsetListener, System.Action`1 remove) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Android.Views.View.remove_Click (System.EventHandler value) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.Droid.Target.MvxViewClickBinding.Dispose (Boolean isDisposing) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.Bindings.MvxBinding.Dispose () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.ClearTargetBinding () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.Dispose (Boolean isDisposing) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.Bindings.MvxBinding.Dispose () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.BindingContext.MvxBindingContext.ClearAllViewBindings () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Binding.BindingContext.MvxBindingContext.ClearAllBindings () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Droid.Fragging.Fragments.MvxBindingFragmentAdapter.HandleDestroyViewCalled (System.Object sender, System.EventArgs e) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.CrossCore.Core.MvxDelegateExtensionMethods.Raise (System.EventHandler eventHandler, System.Object sender) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Cirrious.MvvmCross.Droid.Fragging.Fragments.EventSource.MvxEventSourceDialogFragment.OnDestroyView () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Keiser.IPS.Screen.Droid.Views.SettingsView.OnDestroyView () [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at Android.Support.V4.App.Fragment.n_OnDestroyView (IntPtr jnienv, IntPtr native__this) [0x00000] in <filename unknown>:0 
02-12 07:14:52.504: E/mono-rt(21076):   at (wrapper dynamic-method) object:4bb261f4-79d8-4e2d-80ec-785ea7b637ce (intptr,intptr)

在我看来,MvxViewClickBinding.Dispose方法正在删除事件处理程序,并且在该进程的某个时刻,对象正在消失?检查MvxViewClickBinding. Dispose方法是否检查被触摸的对象是否仍然存在,这样我就会认为Android堆栈中的某个位置正在消失。

我已经打了几个星期了,所以如果你有建议,请告诉我!


编辑1

我添加了在OnCreateDialog方法中充气的视图。

我的意思有时候,对话框中的9次中有9次没有问题,但偶尔会导致应用程序崩溃。我已经看到它使用屏幕上的两个按钮崩溃,以及使用关闭对话框单击或后退按钮。

以下是VS 2013中的追踪:

02-13 03:22:37.084 W/InputEventReceiver(11572): Attempted to finish an input event but the input event receiver has already been disposed.
An unhandled exception occured.

如果我在OnDestroyOnClose方法之后立即触发GC,我可以每次都这样做。

看起来MvxViewClickBinding.Dispose方法非常简单,所以我不确定这是一个Mvx错误。这似乎是Android V4支持库中的一些内容。

以下是设备中的trace.txt文件:https://gist.github.com/bayssmekanique/af33048a94350a819f13

0 个答案:

没有答案