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

本文探讨了在Android开发中Dialog组件的dismiss与hide方法之间的差异。通过对比两种方法的源码实现,揭示了它们在资源管理和显示状态上的不同表现。

对于一般的对话框来说,很多人习惯会用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的底层机制还是有很大的帮助的。

嗯,就到这儿了。







<think>好的,我现在需要帮用户解决关于Android AlertDialoghide方法的问题。用户提到他们想查找hide方法的实现或替代方案。首先,我得回想一下AlertDialog的相关知识。 首先,我记得AlertDialogAndroid中的一个常用对话框类,属于android.app包。用户可能在使用过程中遇到了需要隐藏对话框的情况,但发现AlertDialog本身并没有hide方法。这可能让他们感到困惑,所以需要寻找替代方案。 接下来,我需要确认AlertDialog的文档。查阅Android官方文档,确实,AlertDialog继承自Dialog类,而Dialog类中有show()dismiss()方法,但没有hide()方法。所以用户提到的hide()方法可能不存在于DialogAlertDialog中,这是问题的关键。 用户可能需要暂时隐藏对话框而不是完全关闭它。这时候,替代方案可能包括使用Dialog的setVisibility()方法,但Dialog本身并没有这个方法。可能用户需要操作对话框的Window或者View来实现隐藏效果。 另一个思路是,通过获取对话框的Window对象,然后设置其可见性。例如,使用getWindow().setVisibility(View.GONE)来隐藏对话框的窗口。不过需要注意,这种方法可能会引发空指针异常,因为对话框的Window可能在某些情况下还未创建,特别是在对话框没有显示之前调用这个方法的话。所以用户需要在对话框显示之后再进行操作,比如在onShowListener中执行。 另外,用户可能想通过操作对话框的根布局来隐藏内容。例如,找到根布局的View,然后将其设置为GONE。这可以通过findViewById(android.R.id.content)获取内容视图,然后设置其可见性。不过同样需要注意,在对话框显示之后才能获取到这些视图,否则可能会得到null。 还有,用户可能需要暂时隐藏对话框,稍后再显示。这种情况下,直接调用dismiss()会销毁对话框,无法再次显示。所以替代方法可能需要重新创建对话框实例,或者使用show()dismiss()来控制。不过如果需要保留对话框的状态,可能需要其他方式,比如保持对对话框的引用,并在需要时重新显示。 此外,用户可能在某个特定的场景下需要隐藏对话框,比如在点击某个按钮后暂时隐藏,处理完某些操作后再显示。这时候,结合setOnShowListener按钮的点击事件,可以在按钮点击时执行隐藏操作,比如设置View.GONE,或者操作Window的可见性。 还需要考虑兼容性不同Android版本的问题。某些方法可能在较旧的版本中不可用,或者行为不一致,需要测试验证。 总结一下,可能的替代方案包括: 1. 使用getWindow().setVisibility(View.GONE)来隐藏对话框窗口。 2. 操作对话框的内容视图,设置其可见性为GONE。 3. 使用dismiss()方法关闭对话框,并在需要时重新创建显示。 4. 结合对话框的显示监听器,确保在正确的时间点执行隐藏操作。 需要提醒用户注意,直接操作Window或View的可见性可能会导致对话框无法正确恢复,或者在某些情况下出现UI异常。因此,建议根据具体需求选择合适的方案,并进行充分的测试。 另外,参考用户提供的引用内容,他们在之前的代码中使用了setOnShowListener来修改按钮样式。这可能意味着用户已经熟悉在对话框显示后执行某些操作,因此可以类似地在onShow回调中执行隐藏操作。 最后,需要确认这些替代方案是否有效,可能需要编写示例代码来演示如何实现隐藏效果,并指出潜在的问题注意事项。</think>关于AndroidAlertDialoghide方法实现及替代方案,以下是详细说明: ### 1. 方法特性分析 AlertDialog类继承自Dialog类,Dialog类原生提供`dismiss()``show()`方法,但**没有直接提供hide方法**[^1]。调用`dialog.hide()`会触发编译错误。 ### 2. 替代方案实现 #### 方案一:窗口可见性控制 通过操作对话框的Window对象实现隐藏: ```java AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.show(); // 隐藏对话框窗口 dialog.getWindow().setVisibility(View.GONE); // 重新显示 dialog.getWindow().setVisibility(View.VISIBLE); ``` *注意:需在show()之后调用,否则会触发空指针异常* #### 方案二:视图可见性控制 操作对话框内容视图实现局部隐藏: ```java dialog.setOnShowListener(dialogInterface -> { View contentView = dialog.findViewById(android.R.id.content); contentView.setVisibility(View.GONE); }); ``` ### 3. 生命周期对比 | 方法 | 内存占用 | 可恢复性 | 窗口状态 | |------------|----------|----------|------------| | dismiss() | 释放内存 | 不可恢复 | 完全关闭 | | setVisibility(GONE) | 保持占用 | 立即恢复 | 保留窗口参数 | ### 4. 最佳实践建议 需要临时隐藏时推荐方案一,但要注意: 1. 必须通过`setOnShowListener`确保窗口已初始化 2. 隐藏期间仍占用内存 3. 需自行处理返回键拦截 ```java dialog.setOnShowListener(dialogInterface -> { Window window = dialog.getWindow(); window.setVisibility(View.GONE); // 设置30秒后自动恢复 new Handler().postDelayed(() -> { window.setVisibility(View.VISIBLE); }, 30000); }); ``` 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值