【问题标题】:IllegalStateException: Activity has been destroyed - when app is trying to show DialogFragment once more timeIllegalStateException: Activity 已被破坏 - 当应用程序尝试再次显示 DialogFragment 时
【发布时间】:2014-06-11 05:36:31
【问题描述】:

我在 stackoverflow 上发现了很多类似的问题,但他们的解决方案在我的情况下不起作用。它们尤其与onSaveInstanceState 方法和支持库有关。

我有 Activity 在一个事件上运行此代码:

MyDialogFragment.showMyDialog(name, this, this);

name参数是String对象。第二个参数(this)是刚刚的Activity 类对象,第三个参数(也是this)是简单的接口。这个我的Activity 实现了这个接口。 showMyDialog() 当然是静态方法。这是它的身体:

MyDialogFragment fragment = new MyDialogFragment(listener, "Hello " + name);
fragment.show(activity.getFragmentManager(), "myDialog");

这在第一次尝试时效果很好。但在第二个我得到这个例外:

E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.myapp, PID: 20759
java.lang.IllegalStateException: Activity has been destroyed
        at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1345)
        at android.app.BackStackRecord.commitInternal(BackStackRecord.java:597)
        at android.app.BackStackRecord.commit(BackStackRecord.java:575)
        at android.app.DialogFragment.show(DialogFragment.java:230)
        at com.example.myapp.view.dialog.MyDialogFragment.showMyDialog(MyDialogFragment.java:41)
        at com.example.myapp.MyActivity.showMyDialog(MyActivity.java:208)
        at com.example.myapp.MyActivity.onEvent(MyActivity.java:232)
        at com.example.myapp.MyActivity.handleMessage(MyActivity.java:89)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5017)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
        at dalvik.system.NativeStart.main(Native Method)

一般来说,这是重现我的异常的步骤:

  1. 输入Activity - 收到事件,因此显示MyDialogFragment
  2. 按否定按钮关闭对话框。
  3. 再次输入Activity - 再次显示MyDialogFragment
  4. 在 EditText 中键入一些代码。
  5. 此时验证需要一些时间。与服务器等连接,并返回否定结果。所以需要再次显示MyDialogFragment。但此刻我遇到了异常。

但是,当我跳过第二点并开始输入错误代码进行验证时,MyDialogFragment 将毫无问题地显示出来。奇怪的行为。

我尝试过使用非静态方法setRetainInstance(true)commitAllowingStateLoss。但是没有区别。

【问题讨论】:

  • 你能发布你的Dialog的showMyDialog方法吗?
  • @kupsef 我在我的问题中发布的这个方法的主体。如您所见,这只是两行代码。
  • 如果您使用支持库,您必须调用 getSupportFragmentManager 而不是 getFragmentManager。此外,如果您在片段内,则必须使用 getChildFragmentManager。
  • @MattiaFranchetto 感谢您的建议,但我没有使用支持库

标签: android android-fragments android-dialogfragment illegalstateexception


【解决方案1】:

在方法showMyDialog()第一次尝试:

MyDialogFragment fragment = activity.findFragmentByTag("myDialog");

如果(fragment == null),则初始化:

MyDialogFragment fragment = new MyDialogFragment(listener, "Hello " + name);

否则显示它:

fragment.show(activity.getFragmentManager(), "myDialog");

更新:

void showMyDialog() {
    MyDialogFragment fragment = activity.getFragmentManager().findFragmentByTag("myDialog");
    if (fragment == null) {
        fragment = new MyDialogFragment(listener, "Hello " + name);
    }
    fragment.show(activity.getFragmentManager(), "myDialog");
}

【讨论】:

  • 你的意思是activity.getFragmentManager().findFragmentByTag("myDialog")?
  • 但不幸的是,您的回答不适用于我的情况。另外fragment.show()方法不能在else块中。
  • 是的,我已经按照您更新的方式使用了您的答案。但它没有任何改变。
【解决方案2】:

只需更改以下行

MyDialogFragment.showMyDialog(name, this, this);

MyDialogFragment.showMyDialog(name, **"Activity class name.this"**, this);

【讨论】:

  • 但是showMyDialog() 方法需要Activity 对象作为第二个参数,没有String...
  • np 你误会我的意思了,你不必把它改成字符串。只需将其更改为 ActivityName.this
【解决方案3】:

这有点奇怪 - 或者可能只是这个 Android 功能中的一个错误。我添加了块try catch 以这种方式捕获抛出异常:

MyDialogFragment fragment = new MyDialogFragment(listener, "Hello " + name);
try {
    fragment.show(activity.getFragmentManager(), "myDialog");
} catch (Exception e) {
    e.printStackTrace();
}

当然,异常仍在抛出(并在此时捕获),有趣的是我的对话框片段以正确的方式重新创建并且用户可以与之交互。

【讨论】:

  • 我只是想在 asyncktask 完成后显示一个对话框,但有时用户之前关闭了活动,这段代码解决了问题。
【解决方案4】:

(适用于 API 17 及更高版本)

如果有人仍然有这个问题(甚至与事务的commit() 方法有关),我只是在它之前添加了一个检查:

private showFragment() {
    if (isDestroyed()) {
        return;
    }

    // Else do whatever transaction...
}

【讨论】:

    【解决方案5】:

    我在尝试在 DialogFragment 中添加 SupportMapFragment 时遇到了同样的错误。我可以通过使用getChildFramentManager() 而不是getFragmentManager() 来修复此错误,正如API 在使用嵌套片段时所建议的那样:

    public class GpsDialogFragment extends DialogFragment {
        private SupportMapFragment mapFragment;
        private static final String MAP_FRAGMENT_TAG = "MAP_FRAGMENT";
    
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.gps_postition_dialog, container, false);
            // ...
    
            // dynamically create the map fragment (https://stackoverflow.com/questions/14083950)
            FragmentManager fragmentManager = getChildFragmentManager();
            mapFragment = (SupportMapFragment) fragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG);
            if (mapFragment == null) {
                if (!getActivity().isFinishing()) {
                    mapFragment = new SupportMapFragment();
                    FragmentTransaction ft = fragmentManager.beginTransaction();
                    ft.add(R.id.mapFrame, mapFragment, MAP_FRAGMENT_TAG);
                    ft.commit();
                    fragmentManager.executePendingTransactions();
                }
            }
    
            return view;
        }
    
        // ...
    
        @Override
        public void onPause() {
            if (mapFragment != null)
                getChildFragmentManager().beginTransaction().remove(mapFragment).commit();
            super.onPause();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-10
      • 2013-01-25
      • 1970-01-01
      • 2014-10-07
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多