Android为啥推荐用DialogFragment创建Dialog?

本文探讨了为何在Android 3.0后推荐使用DialogFragment替代AlertDialog和PopupWindow。DialogFragment拥有与Fragment相似的生命周期,能更好地适应屏幕旋转,并解决横竖屏切换时Dialog消失的问题。通过分析DialogFragment的源码,展示了如何通过重写onCreateView或onCreateDialog方法创建自定义Dialog,并通过实例展示了两种创建DialogFragment的方式,强调了在横竖屏切换时DialogFragment的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:这段时候有点忙,因为在赶项目,说忙也都是在敷衍,时间挤挤还是有的,从开始写博客的那一刻起就应该一直坚持下来,不要三天打鱼两天晒网,上次写过一个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(
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值