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

时间:2017-09-20 21:12:45

标签: android android-fragments android-dialogfragment

我经常需要来自自定义类的用户交互(对话框),这些自定义类不是Activity或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();
            }
        }
    }

}

不幸的是,在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)

我使用的片段管理器不知道这个内部类是有意义的,但是替代方案是什么?我尝试使用内部类作为片段管理器...

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

...并且没有崩溃,但是对话框没有出现,可能是因为从不显示监听器片段。

我可以快速修复我当前的方法,或采用不同的方法来完成同样的事情(但更喜欢快速修复!)。

1 个答案:

答案 0 :(得分:0)

在写出问题时,我有一个基于“从不显示监听器片段”的想法。我在显示对话框之前添加了这一行:

R version 3.4.1 (2017-06-30)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.6

Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggplot2_2.2.1.9000 prompt_1.0.0       colorout_1.1-2    

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.12      memuse_3.0-1      clisymbols_1.2.0  crayon_1.3.2     
 [5] grid_3.4.1        plyr_1.8.4        gtable_0.2.0      scales_0.5.0.9000
 [9] rlang_0.1.2       lazyeval_0.2.0    labeling_0.3      munsell_0.4.3    
[13] compiler_3.4.1    colorspace_1.3-2  tibble_1.3.4   

我认为这可以让片段管理器知道我的监听器片段,因此它不会抛出异常。

这似乎是一个简单而合理的解决方案,但我仍然对其他方法持开放态度。