Android开发,源码分析Dialog/AlertDialog的dismiss()和hide()的区别

来源:互联网 发布:暴雨网络天书九卷官网 编辑:程序博客网 时间:2024/06/11 01:34

对于一般的对话框来说,很多人习惯会用dismiss,因为并没有太大的区别。

但对于某些需要保存资源的对话框,比如地图控件,当dismiss后,再次打开,就会发现地图无法加载了,因为资源已经被清除了。

类似的还有滚动条状态,图片加载状态等等。

其实说区别,从名字上就能看出来,一个是取消,一个是隐藏。

本文主要从源码的角度看他们的区别。

@Override    public void dismiss() {        if (Looper.myLooper() == mHandler.getLooper()) {            dismissDialog();        } else {            mHandler.post(mDismissAction);        }    }
public void hide() {        if (mDecor != null) {            mDecor.setVisibility(View.GONE);        }    }
先看hide,这里涉及到一个mDecor的参数,我初步猜想是dialog的view的承载控件。
public void show() {...mDecor = mWindow.getDecorView();...}
赋值位置在show方法里面。

这里的getDecorView,可以看到如下代码:

/**     * Retrieve the top-level window decor view (containing the standard     * window frame/decorations and the client's content inside of that), which     * can be added as a window to the window manager.     *     * <p><em>Note that calling this function for the first time "locks in"     * various window characteristics as described in     * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}.</em></p>     *     * @return Returns the top-level window decor view.     */    public abstract View getDecorView();
即返回顶层窗口的视图,很有意思的是,这里返回的是顶层窗口,并没有指定为哪一个窗口,理论上是会出现找错窗口的情况的,但是事实上,该方法是紧跟在show方法上的,show之后立即获取,不会出现找错窗口的情况。

再深我们就暂时不看了,接着看看dismiss方法。

它首先通过:

if (Looper.myLooper() == mHandler.getLooper()) {}
判断了当前线程是否是dialog的所在线程,如果是,就调用dismissdialog,如果不是则将dissmissaction这个操作,传递给dialog所在handle进行处理,我比较感兴趣这个dissmissaction这个参数。

 private final Runnable mDismissAction = this::dismissDialog;
可以看到,这里出现了一个双冒号的使用,这是java8中引入的lambda的语法,可以等同于以下:

private final Runnable mDismissAction = new Runnable() {            @Override            public void run() {                dismissDialog()            }        }

很简洁的语法,android26的源码中已经开始大范围的使用lambda的语法了,所以推荐各位平时多尝试不同的lambda,并不只是使用android studio 3.0+默认的alt+enter转lambda,因为很多地方,是不会告诉你可以这样写的。

这里的dismissdialog:

void dismissDialog() {        if (mDecor == null || !mShowing) {            return;        }        if (mWindow.isDestroyed()) {            Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");            return;        }        try {            mWindowManager.removeViewImmediate(mDecor);        } finally {            if (mActionMode != null) {                mActionMode.finish();            }            mDecor = null;            mWindow.closeAllPanels();            onStop();            mShowing = false;            sendDismissMessage();        }    }
很直白的语句,先判断承载窗口view是否为空,或者dialog是否没有展示,如果是,就return掉。

然后判断,window是否已销毁,如果是,继续return。

最后通过windowmanager去移除承载窗口view-mDecor。

清除资源、回调关闭状态、发送关闭信息、改变dialog状态等等一系列操作。


源码就看到这,其实,大部分的源码,我们都没必要去看,因为具体的区别在前两段源码就足以看清楚区别了。

但我还是继续往里面挖了一下,可能对我们分析没有太大的用处,但是对于了解dialog的底层机制还是有很大的帮助的。

嗯,就到这儿了。







原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝用红包退款怎么办 快递不能改地址怎么办 超市买到假货怎么办 天猫不小心删除了怎么办 生活费都没了怎么办 天猫超市发错货怎么办 双11退货红包怎么办 充电线不在充电怎么办 淘宝直播不清晰怎么办 手机扫码不清楚怎么办 安卓软件删不掉怎么办 顾客恶意差评怎么办 淘宝不能看视频怎么办 天猫精灵打不开怎么办 手机淘宝卡死了怎么办 为什么电视盒子打不开怎么办 天猫买了降价了怎么办 试用报告未提交怎么办 试用中心拉黑怎么办 淘宝赠品破了怎么办 淘宝卖家不给赠品怎么办 淘宝赠品有瑕疵怎么办 淘宝赠品不发货怎么办 移动电视没信号怎么办 网络电视死机了怎么办 电视接收网络信号不好怎么办 tcl电视待机打不开怎么办 宽带电视看不了怎么办 电视总是闪退怎么办 电视出现系统更新怎么办 电视一直在更新怎么办 电视更新死机了怎么办 法院打电话不接怎么办 内向不敢辞职怎么办呀 生气后睡不着觉怎么办 被气得睡不着怎么办 一生气就睡不着怎么办 手机接电话声音小怎么办 发微信老公不回怎么办 欠钱没有欠条怎么办 朋友欠钱不还怎么办没欠条