@946898963
2020-06-11T17:58:55.000000Z
字数 2062
阅读 1676
Android学习笔记
自我感觉DialogFragment似乎没有那么好用,主要就是show的时候需要传递FragmentManager(),这就需要调用getSupportFragmentManager()方法,而这个方法需要传递上下文才能获取,有些场景下上下文不好传递进去,所以这种场景下反而不如Dialog或者Dialog类型的Activity好用。
DialogFragment 是系统提供的一种特殊Fragment,通过调用show()方法即可展示Dialog,使用中也需要注意一点。比如,通常触发场景是,用户点击某个按钮,弹出 Dialog。如果你是这么写的话:
if (mDialogFragment == null) {
mDialogFragment = SampleDialogFragment.newInstance();
}
mDialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_SAMPLE);
}
可以看到,为了避免重复创建对象,对DialogFragment做了判空处理。这种写法本身没有错,但如果用户连续点击按钮,导致同一时刻多次触发show操作,你会发现,App立马崩溃退出,并在logcat 提示如下错误信息:
java.lang.IllegalStateException: Fragment already added: a{8fd950d #0 XXXDialogFragment}
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1361)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:734)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:536)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5669)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
错误信息间接指向show()方法,因为该方法内部调用fragment的add()方法。如果有间隔地点次点击按钮触发show()方法,就不会发生这个问题。这是为什么呢?仔细看看show()方法的注释,里面有这么一段内容:
This does not add the transaction to the back stack. When the fragment is dismissed, a new transaction will be executed to remove it from the activity.
这也就解释了为什么间隔点击不会报错的原因。除了第一次触发,间隔触发时前面一定调用过dismiss() 方法 (dialog 消失),也就是 remove 过 fragment 对象。而连续多次触发时,导致对同一个 fragment 对象多次执行 add 操作,导致报错。知道原因后,解决方案也就有啦。
我们可以对按钮做点击排重处理,更简单点处理就是直接在 show() 之间添加判断,代码如下:
if (mDialogFragment == null) {
mDialogFragment = SampleDialogFragment.newInstance();
}
Dialog mDialog = SampleDialogFragment.getDialog();
if (mDialog==null || !mDialog.isShowing()) {
mDialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_SAMPLE);
}