【问题标题】:DialogFragment/FragmentManager crash on rotation (Using MVVMCross) :IllegalStateException: Can not perform this action after onSaveInstanceStateDialogFragment/FragmentManager 在旋转时崩溃(使用 MVVMCross):IllegalStateException:在 onSaveInstanceState 之后无法执行此操作
【发布时间】:2015-07-09 15:01:45
【问题描述】:

我见过其他人遇到类似的问题,但我的情况有点不同。我不确定这是 MVVMCross 问题还是 Androind.Support.V4 库有问题。我正在使用 Xamarin Studio。

我有一个管理 FragmentDialog 的活动。

在我的 OnCreate 方法中,我检查是否正在显示现有的 DialogFragment。这适用于 DialogFragment 已经打开并发生旋转的情况。在每个 OnCreate 上,我使用分配的标签查找对话框。 MVVMCross 使用支持库作为其 MXVFragmentAcitivity 的一部分。我使用实现 getter 的属性 SupportFragmenetManager 获得 FragmentManager(我相信是私有 setter)。

第一次创建活动时,一切都按预期工作。已经打开的对话框不会导致任何问题,因为它正在 OnCreate 方法中得到处理。

我做的第一件事是 base.OnCreate(bundle)。

当我旋转屏幕然后尝试调用我的对话框时出现问题。

根据我的调试和跟踪,当旋转发生时,OnDetroy 会按预期调用。我检查了 SupportFragmentManager 的状态。此时它被标记为被销毁。

当使用 OnCreate 创建新活动时,我检查 SupportFragmentManager 并看到有一个新实例。有道理。

我通过 OnViewModelSet 和 OnResume 对其进行了跟踪,一切都很好。

视图设置完毕后,我单击所需的按钮来调用对话框。第一次调用对话框的步骤相同。

应用在 dialog.show(SupportFragmentManager, dialogName); 上崩溃;

我可以看到旧的 SupportFragmentManager 正在被调用。它没有任何意义。我认为该活动正在以某种方式重新加载旧的 FragmentManger。是否有可能将其存储在捆绑包中并在某一时刻恢复。基于 Android 文档 OnRestoreInstance 发生在 OnResume 之前。如前所述,当我在 OnResume 中检查 SupportFragmentManager 时,它有一个新值。

我有点困惑。收到的异常是:java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

这是我所拥有的代码的简短版本:

Activity OnCreate:

protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
            SetContentView (Resource.Layout.session_page_layout);
            Window.AddFlags (WindowManagerFlags.KeepScreenOn);

            var existingDialog = (ConnectionDialogFragment)SupportFragmentManager.FindFragmentByTag(BLEDialogTagName);
            if (existingDialog != null)
                existingDialog.ViewModel = Mvx.GetSingleton<IDeviceList>() as DeviceListVM;//Mvx.IocConstruct<DeviceListVM> ();
        }

FragmentDialog OnCreateDialog:

public override Dialog OnCreateDialog(Bundle savedState)
        {
            base.EnsureBindingContextSet(savedState);
            var view = this.BindingInflate(Resource.Layout.DeviceListView, null);
            var dialog = new AlertDialog.Builder(Activity);
            dialog.SetTitle(title);
            dialog.SetView(view);
            dialog.SetNeutralButton("Close", (s, a) => { Dismiss();});
            return dialog.Create();
        }

以及来自 Activity 的调用:

private void ShowDeviceDialog()
        {
            var dialog = new ConnectionDialogFragment ();
            //Removed ViewModel setting as it is irrelavent
            dialog.Show (SupportFragmentManager, BLEDialogTagName);  
        }

如果有人能对这个问题有所了解,我将不胜感激。我见过类似的问题,但似乎这些与对话框启动时的旋转和应用程序崩溃有关。同样,当对话框启动并发生旋转时,我不会崩溃。 OnCreate 中 SupportFragmentManager 的状态良好且正确。临时解决方法是将屏幕锁定到某个方向。在找出问题所在之前,我将其锁定为肖像。

【问题讨论】:

  • 您使用的是哪个版本的 MvvmCross?您能否上传一个小型示例项目,以便可以复制并在 MvvmCross 存储库中填写一张票?您是否还知道我们已经更新了 Android 支持库:github.com/MvvmCross/MvvmCross-AndroidSupport
  • @Martijn00 我现在使用的是 3.5.1。我昨天用我的答案更新了这个问题。经过进一步调查,我发现先前销毁的(由于屏幕旋转)活动中的事件未正确清理。像这样: OnCreate() { testEvent += test; } OnDestroy() { //缺少这一行 //testEvent -= test;添加 OnDestory 事件清理后,一切都开始正常工作。我创建了一个通用的 DialogFragment 并在其他情况下使用它,它就像一个魅力。感谢您检查

标签: android mvvmcross android-support-library android-dialogfragment fragmentmanager


【解决方案1】:

经过进一步调查,我发现我在 OnCreate 中注册了一个事件,但在该活动被销毁时我未能从该事件中取消注册。因此,事件处理程序仍会向已销毁的旧活动发送消息。在 OnDestroy 中添加这个解决了这个异常。我在 Android 5 上对此进行了测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 2012-12-25
    • 2014-03-05
    • 2011-11-26
    • 1970-01-01
    • 2015-11-26
    相关资源
    最近更新 更多