前言:这段时候有点忙,因为在赶项目,说忙也都是在敷衍,时间挤挤还是有的,从开始写博客的那一刻起就应该一直坚持下来,不要三天打鱼两天晒网,上次写过一个Android进阶之(dialog详解一),今天继续上次的内容探究一下,从Android3.0后Android引入的DailogFragment,我们一起从源码的角度去看看为啥谷歌推荐这样创建Dialog.
DialogFragment对话框出现的意义
为什么android系统有AlertDialog,PopupWindow对话框,基本满足客户需求,为啥还要跑出一个DialogFragment对话框呢?
这就要从DialogFragment的优点说起了:
有和Fragment基本一致的生命周期,因此便于Activity更好的控制管理DialogFragment。 随屏幕旋转(横竖屏幕切换)DialogFragment对话框随之自动调整对话框大小。而AlertDialog和PopupWindow随屏幕切换而消失。 DialogFragment的出现解决 横竖屏幕切换Dialog消失的问题。
既然是探究性的话题,我们就从DialogFragment源码探究一下。
在此次之前先贴一张Fragment的生命周期图:
DialogFragment的全部源码我就不贴了,要研究的童鞋就多按按Ctrl+左键吧(^__^) 嘻嘻……我们按照Fragment的生命周期一个一个往下看,揭开它的神秘面纱。
首先看看onAttach()方法
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (!mShownByMe) {
// 如果不是通过调用DialogFragment自己的show方法弹出Dialog的话
// 标志着这个Dialog不再被消失
mDismissed = false;
}
}
这个方法也没什么重要代码。
接下来看看onCreate()方法
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mShowsDialog = mContainerId == 0;
if (savedInstanceState != null) {
mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);
mTheme = savedInstanceState.getInt(SAVED_THEME, 0);
mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);
mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);
}
}
当Activity生命周期发生变换的时候,也就是比如切换横竖屏的时候,对Dialog的一些属性进行保存,当再次创建Fragment的时候回到上一次Dialog的状态,既然有取的过程,那必定有存的过程。
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mDialog != null) {
Bundle dialogState = mDialog.onSaveInstanceState();
if (dialogState != null) {
outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState);
}
}
if (mStyle != STYLE_NORMAL) {
outState.putInt(SAVED_STYLE, mStyle);
}
if (mTheme != 0) {
outState.putInt(SAVED_THEME, mTheme);
}
if (!mCancelable) {
outState.putBoolean(SAVED_CANCELABLE, mCancelable);
}
if (!mShowsDialog) {
outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
}
if (mBackStackId != -1) {
outState.putInt(SAVED_BACK_STACK_ID, mBackStackId);
}
}
紧接着我们看到这么一个方法:
/** @hide */
@Override
public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
if (!mShowsDialog) {
return super.getLayoutInflater(savedInstanceState);
}
mDialog = onCreateDialog(savedInstanceState);
if (mDialog != null) {
setupDialog(mDialog, mStyle);
return (LayoutInflater) mDialog.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
return (LayoutInflater) mHost.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
这个方法虽然隐藏了,但是我们看到,在方法里面new了一个Dialog,onCreateDialog,所以我们知道,其实DialogFragment里面也是悄悄的创建了一个Dialog,创建了一个Dialog,那系统怎么知道我们创建的Dialog的样式呢?总要一些Dialog的初始化吧?
带着疑问,接着我们看看onActivityCreated这个方法:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (!mShowsDialog) {
return;
}
View view = getView();
if (view != null) {
if (view.getParent() != null) {
throw new IllegalStateException(
"DialogFragment can not be attached to a container view");
}
mDialog.setContentView(view);
}
final Activity activity = getActivity();
if (activity != null) {
mDialog.setOwnerActivity(activity);
}
mDialog.setCancelable(mCancelable);
mDialog.setOnCancelListener(