简体   繁体   English

自定义类的对话框在Android O中崩溃

[英]Dialogs from custom classes crash in Android O

I often need user interaction (dialogs) from custom classes that aren't subclasses of Activity or Fragment. 我经常需要来自不是Activity或Fragment子类的自定义类的用户交互(对话框)。 Here's an example of how I'm currently doing this. 这是我目前如何执行此操作的示例。 I open the dialog from the fragment manager of the fragment that created the custom class, and I use a small inner class as the target so I can get the dialog result. 我从创建自定义类的片段的片段管理器中打开对话框,并使用一个较小的内部类作为目标,以便获得对话框结果。 This keeps all the related code in one place, as opposed to putting onActivityResult in the parent fragment: 与将onActivityResult放在父片段中相反,这会将所有相关代码放在一个位置:

public class DocumentViewer extends RelativeLayout {

    public void deleteAnnotations() {
        DialogFragment dialog = new DialogFragment();
        Bundle args = new Bundle();
        args.putString("title", this.app.getString(R.string.DELETE_ANNOTATIONS));
        args.putString("message", this.app.getString(R.string.CONFIRM_DELETE_ANNOTATIONS));
        args.putString("button1Text", this.app.getString(R.string.BUTTON_DELETE));
        args.putString("button2Text", this.app.getString(R.string.BUTTON_CANCEL));
        dialog.setArguments(args);
        DocumentViewerAlertListener listener = new DocumentViewerAlertListener();
        listener.canvas = this.canvas;
        dialog.setTargetFragment(listener, R.id.confirmDelete);
        dialog.show(this.fragment.getFragmentManager(), "confirmDelete");
    }

    public static class DocumentViewerAlertListener extends ALFragment {
        public ALCanvas canvas;

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
            if ((requestCode == R.id.confirmDelete)&&(resultCode == 1)) {
                this.canvas.clearItems();
            }
        }
    }

}

Unfortunately, in Android O, the dialog.show line crashes with this stack trace: 不幸的是,在Android O中,dialog.show行因以下堆栈跟踪而崩溃:

09-20 14:06:12.852 24301-24301/com.bizname.appname E/AndroidRuntime: FATAL EXCEPTION: main
  Process: com.bizname.appname, PID: 24301
  java.lang.IllegalStateException: Fragment ALAlert{1ace4cd #8 confirmDelete} declared target fragment DocumentViewerAlertListener{7e21182} that does not belong to this FragmentManager!
      at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1209)
      at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1549)
      at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1611)
      at android.app.BackStackRecord.executeOps(BackStackRecord.java:807)
      at android.app.FragmentManagerImpl.executeOps(FragmentManager.java:2394)
      at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2189)
      at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2142)
      at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2049)
      at android.app.FragmentManagerImpl$1.run(FragmentManager.java:718)
      at android.os.Handler.handleCallback(Handler.java:789)
      at android.os.Handler.dispatchMessage(Handler.java:98)
      at android.os.Looper.loop(Looper.java:164)
      at android.app.ActivityThread.main(ActivityThread.java:6541)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

It makes sense that the fragment manager I'm using doesn't know about this inner class, but what's the alternative? 我正在使用的片段管理器对这个内部类一无所知,这是有道理的,但是还有什么选择呢? I tried using the inner class as the fragment manager... 我尝试使用内部类作为片段管理器...

dialog.show(listener.getFragmentManager(), "confirmDelete");

...and there was no crash, but the dialog didn't appear, perhaps because the listener fragment is never displayed. ...并且没有崩溃,但是没有出现对话框,可能是因为从未显示侦听器片段。

I'm open to either a quick fix for my current approach, or a different approach that accomplishes the same thing (but would prefer a quick fix!). 我愿意采用当前方法的快速解决方案,也可以采用可以完成相同任务的其他方法(但希望采用快速解决方案!)。

While writing out the question, I had an idea based on "the listener fragment is never displayed." 在写问题时,我有一个基于“永远不会显示监听器片段”的想法。 I added this line before showing the dialog: 我在显示对话框之前添加了以下行:

this.fragment.getFragmentManager().beginTransaction().add(listener, "confirmDelete").commit();

I assume this lets the fragment manager know about my listener fragment, so it doesn't throw the exception. 我假设这会让片段管理器知道我的侦听器片段,因此它不会引发异常。

This seems like an easy and logical fix, but I'm still open to other approaches. 这似乎是一个简单且合乎逻辑的解决方案,但我仍然对其他方法持开放态度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM