如何从处理程序显示 DialogFragment

发布于 2025-01-01 17:43:29 字数 2057 浏览 2 评论 0原文

我有一个处理程序,它在收到特定消息时显示 DialogFragment。这通常有效,但如果片段已保存,我会收到以下错误:

E/AndroidRuntime(3898):致命异常:main E/AndroidRuntime(3898):java.lang.IllegalStateException:onSaveInstanceState后无法执行此操作 E / AndroidRuntime(3898):在android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299) E / AndroidRuntime(3898):在android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310) E / AndroidRuntime(3898):在android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541) E / AndroidRuntime(3898):在android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525) E / AndroidRuntime(3898):在android.support.v4.app.DialogFragment.show(DialogFragment.java:123) E / AndroidRuntime(3898):在com.malauzai.app.BaseActivity $ 2.handleMessage(BaseActivity.java:72) E / AndroidRuntime(3898):在android.os.Handler.dispatchMessage(Handler.java:99)

现在,我知道这是预期的,基于 FragmentManager.beginTransaction 的 Javadoc:

注意:片段事务只能在活动保存其状态之前创建/提交。如果您尝试在 Activity.onSaveInstanceState() 之后(在后续 Activity.onStart 或 Activity.onResume() 之前提交事务,您将收到错误。这是因为框架负责将当前片段保存在状态中) ,如果在保存状态后进行更改,则这些更改将会丢失。

我的问题是我不知道如何阻止它,我已尝试调用 Handler.removeMessages()onPause(),但它仍然发生,我尝试在 onSaveInstanceState() 中设置一个标志,并且如果设置了则不显示片段,但它仍然发生。就像一个非常常见的问题,但我无法想出一个有效的解决方案。基本上,我如何知道片段已被保存?

顺便说一句,这发生在我的 BaseActivity (扩展 FragmentActivity)上,但每个活动都有它的自己的处理程序,所以我认为这不应该是一个问题。

我最后的想法是使用 Fragment.commitAllowingStateLoss(),但这看起来像是一个 hack。

编辑: 这是给我带来问题的代码:

private final Handler mTimerHandler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
        switch (msg.what) {
        case TIMER_MESSAGE_LOGOUT_WARNING:
            // throws IllegalStateException if fragment is already saved
            new LogoutWarningDialog().show(getSupportFragmentManager(),
                    "dialog");
            break;
        }
      }
};

I have a Handler which displays a DialogFragment when it receives a particular message. This usually works, but if the fragment has already been saved, I get the following error:

E/AndroidRuntime( 3898): FATAL EXCEPTION: main
E/AndroidRuntime( 3898): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
E/AndroidRuntime( 3898): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299)
E/AndroidRuntime( 3898): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310)
E/AndroidRuntime( 3898): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
E/AndroidRuntime( 3898): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
E/AndroidRuntime( 3898): at android.support.v4.app.DialogFragment.show(DialogFragment.java:123)
E/AndroidRuntime( 3898): at com.malauzai.app.BaseActivity$2.handleMessage(BaseActivity.java:72)
E/AndroidRuntime( 3898): at android.os.Handler.dispatchMessage(Handler.java:99)

Now, I know that this is expected, based on the Javadoc for FragmentManager.beginTransaction:

Note: A fragment transaction can only be created/committed prior to an activity saving its state. If you try to commit a transaction after Activity.onSaveInstanceState() (and prior to a following Activity.onStart or Activity.onResume(), you will get an error. This is because the framework takes care of saving your current fragments in the state, and if changes are made after the state is saved then they will be lost.

My problem is that I can't tell how to prevent it. I've tried calling Handler.removeMessages() on onPause(), but it still occurs. I've tried setting a flag in onSaveInstanceState() and not showing the fragment if it's set, but it still occurs. This seems like a pretty common problem, but I can't come up with a solution that works. Basically, how do I know that the fragment has already been saved?

BTW, this occurs on my BaseActivity (extends FragmentActivity), but each activity has its own handler, so I don't think this should be an issue.

My last thought is using Fragment.commitAllowingStateLoss(), but that seems like a hack.

EDIT:
Here's the code that's causing me problems:

private final Handler mTimerHandler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
        switch (msg.what) {
        case TIMER_MESSAGE_LOGOUT_WARNING:
            // throws IllegalStateException if fragment is already saved
            new LogoutWarningDialog().show(getSupportFragmentManager(),
                    "dialog");
            break;
        }
      }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

糖果控 2025-01-08 17:43:29

我在回答中假设您正在使用 FragmentManager 并通过带有标签(或 ids)的 FragmentTransacts 添加片段。
所以基本上在你的 BaseActivity 中你可以做这样的事情

FragmentManager manager = getFragmentSupportedManager();
Fragment fragmentIWannaKnowIfexists = manager.findFragmentByTag("Tag I used to create this Fragment inside FragmentTrasnsaction")
// or manager.findFragmentById(ID_FROM_LAYOUT)
if(fragmentIWannaKnowIfexists != null){
    //we have this Fragment already
} else {
    // this Fragment was not added already
}

I assume in my answer that you are using FragmentManager and add Fragments through FragmentTransacts with tags (or ids).
so basically inside your BaseActivity you could just do something like this

FragmentManager manager = getFragmentSupportedManager();
Fragment fragmentIWannaKnowIfexists = manager.findFragmentByTag("Tag I used to create this Fragment inside FragmentTrasnsaction")
// or manager.findFragmentById(ID_FROM_LAYOUT)
if(fragmentIWannaKnowIfexists != null){
    //we have this Fragment already
} else {
    // this Fragment was not added already
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文