一、 前述
DialogFragment從名字上來就可以理解:它是fragment,具有dialog的特性。
二、 方案
關(guān)于顯示可以使用FragmentTransaction,因?yàn)樗旧硎荈ragment。
關(guān)于dismiss:
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
if (!mViewDestroyed) {
// Note: we need to use allowStateLoss, because the dialog
// dispatches this asynchronously so we can receive the call
// after the activity is paused. Worst case, when the user comes
// back to the activity they see the dialog again.
dismissInternal(true, true);
}
}
void dismissInternal(boolean allowStateLoss, boolean fromOnDismiss) {
if (mDismissed) {
return;
}
mDismissed = true;
mShownByMe = false;
if (mDialog != null) {
// Instead of waiting for a posted onDismiss(), null out
// the listener and call onDismiss() manually to ensure
// that the callback happens before onDestroy()
mDialog.setOnDismissListener(null);
mDialog.dismiss();
if (!fromOnDismiss) {
// onDismiss() is always called on the main thread, so
// we mimic that behavior here. The difference here is that
// we don't post the message to ensure that the onDismiss()
// callback still happens before onDestroy()
if (Looper.myLooper() == mHandler.getLooper()) {
onDismiss(mDialog);
} else {
mHandler.post(mDismissRunnable);
}
}
}
mViewDestroyed = true;
if (mBackStackId >= 0) {
requireFragmentManager().popBackStack(mBackStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
mBackStackId = -1;
} else {
FragmentTransaction ft = requireFragmentManager().beginTransaction();
ft.remove(this);
if (allowStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
}
}
可以發(fā)現(xiàn),如果使用DialogFragment.dismiss()方法或者按鍵回退觸發(fā)dismiss都會調(diào)用dismissInternal(true, true);最終都會調(diào)用FragmentTransaction.remove(this),這就是銷毀了fragment。很多情況下,需要保留彈窗狀態(tài)的,而此時就不滿足要求了。
——>所以可以覆寫onDismiss方法。
@Override
public void onDismiss(DialogInterface dialog) {
//注釋掉super方法調(diào)用,因?yàn)樵摲椒〞沟肍ragment銷毀
// super.onDismiss(dialog);
}
查看源碼可以發(fā)現(xiàn)DialogFragment其實(shí)是:Dialog中包裹了Fragment。
那么其顯示隱藏其實(shí)是可以直接使用dialog.show()or dialog.hide()來實(shí)現(xiàn)的。
使用getDialog().hide()后,息屏再打開時結(jié)果整個彈窗重新出現(xiàn)了,原因如下:
@Override
public void onStart() {
super.onStart();
if (mDialog != null) {
mViewDestroyed = false;
mDialog.show();
}
}
@Override
public void onStop() {
super.onStop();
if (mDialog != null) {
mDialog.hide();
}
}
如何屏蔽掉上面生命周期中的執(zhí)行代碼對dialog的影響?
手動在生命周期中show() or hide()
直接注釋掉super.onStart()不可以么?
不可以,會導(dǎo)致生命周期紊亂。而且ide會爆紅,因?yàn)檫@里api(Fragment)用了一個注解:@CallSuper
/**
* Called when the Fragment is visible to the user. This is generally
* tied to {@link Activity#onStart() Activity.onStart} of the containing
* Activity's lifecycle.
*/
@CallSuper
public void onStart() {
mCalled = true;
}
//追蹤C(jī)allSuper定義
/**
* Denotes that any overriding methods should invoke this method as well.
* <p>
* Example:
* <pre><code>
* @CallSuper
* public abstract void onFocusLost();
* </code></pre>
*/
@Documented
@Retention(CLASS)
@Target({METHOD})
public @interface CallSuper {
}
可以發(fā)現(xiàn),凡是被@CallSuper注解的方法,都必須在覆寫的方法中回調(diào)。于是,無論如何都不能去掉super.onStart()or super.onStop()。
三、 結(jié)論
就案例中提到的需求而言,這樣使用DialogFragment是比較繁瑣的,還不如直接使用Dialog包裹Fragment。 對API不了解的情況下,還是慎用。
看完文章,如果有幫助,不忘點(diǎn)個贊or喜歡!