Android:在啥情况下出现对话框会导致 onPause() 被调用?

Posted

技术标签:

【中文标题】Android:在啥情况下出现对话框会导致 onPause() 被调用?【英文标题】:Android: Under what circumstances would a Dialog appearing cause onPause() to be called?Android:在什么情况下出现对话框会导致 onPause() 被调用? 【发布时间】:2011-11-06 15:24:39 【问题描述】:

android Activities 文档中的 sn-p(向下滚动到“前台生存期”行)说:

一个活动可以频繁地进出前台——例如 例如,onPause() 在设备进入睡眠状态时调用 对话框出现

我不太明白这个。在什么情况下会发生这种情况? onPause() 是否仅在相关对话框的上下文与要在其上显示对话框的 Activity 不同时才调用?

编辑:添加代码示例以详细说明我的疑问

按照上面提到的文档引用,当下面代码中的AlertDialog(或只是Dialog)显示时,我的活动的onPause() 方法是否应该被调用?显示对话框时是否应该看到“onPause called”日志条目?

但我不认为会发生这种情况。如果我正确理解了 Android 生命周期,它也不应该!那么,文件指向的是什么?

public class LifeCycleTestActivity extends Activity 

    private static final String TAG = "LifeCycleTest";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btn = (Button) findViewById(R.id.button1);

        btn.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(View v) 
                Log.d(TAG, "onClick");

                AlertDialog dialog = new AlertDialog.Builder(LifeCycleTestActivity.this).create();
                 dialog.setMessage("You Clicked on the button");
                 dialog.setTitle("Dialog!");
                 dialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() 

                    @Override
                    public void onClick(DialogInterface dialog, int which) 
                        dialog.dismiss();
                    
                );
                 dialog.setCancelable(true);
                 dialog.show();


                /*
                Dialog dialog = new Dialog(LifeCycleTestActivity.this);
                 dialog.setTitle("Dialog!");
                 dialog.setCancelable(true);
                 dialog.show();
                */
            
        );        
    

    @Override
    protected void onPause() 
        Log.d(TAG, "onPause() called");
        super.onPause();

    

    @Override
    protected void onResume() 
        super.onResume();
        Log.d(TAG, "onResume() called");
    

【问题讨论】:

【参考方案1】:

onPause() 在您的活动不再位于活动堆栈顶部时被调用。 Dialog本身不是Activity,所以不会替换栈顶的当前Activity,所以不会造成任何暂停。

但是,对话框(小写)不需要由 Dialog 类实现。例如,使用主题设置为对话框主题的 Activity 来实现一个并不少见。在这种情况下,显示 dialog-as-an-Activity 将导致新 Activity 位于堆栈顶部,暂停之前的位置。

【讨论】:

很好的答案。我没有想到“对话即活动”。以及 onPause() 仅在对话框位于堆栈顶部时调用的原因 - 这也解释了为什么即使将通知栏拉到底部也不会调用 onPause(),从而完全掩盖了活动。 @curioustechizen 这里有很多微妙之处......感谢您的问题(以及来自 Android 团队的这位了不起的专业人士的回答),我能够很快理解为什么我在我的应用程序中观察正是你观察到的。 +1。 @hackbod :系统对话框也会导致 onPause()。我在查看与棉花糖权限相关的系统对话框时看到了这一点! @abat 这可能是因为权限对话框被实现为一个活动,其主题设置为对话框【参考方案2】:

我已经用对话框编写了很多代码,包括您提到的AlertDialog,并且我还尝试检查对话框弹出时是否在活动上调用onPause(),但是到目前为止我的结论是该活动只是继续运行并且onPause() 没有被调用

不确定它是否有帮助,但至少你现在知道还有其他人经历过你正在经历的事情:-)

【讨论】:

好吧,实际上,如果我正确理解了生命周期,我相信对话不能触发onPause()。所以观察到的行为与预期的一致。只是我偶然发现了我引用并链接到的这条信息。这让我走上了迷茫的道路!【参考方案3】:

活动在 onPause 阶段不再保持在活动堆栈的顶部是错误的。

将活动设置为 onPause 状态 -

活动部分可见,例如活动对话框。

Activity 对象保留在内存中,它维护所有状态和成员信息,并保持连接到窗口管理器。

例如,按下主页按钮会导致活动进入 onPause()。仍然在栈顶。

在图 1 中,Activity3 将被销毁并从栈顶移除

在图 2 中。现在任务 A 进入后台,但 Activty X 仍在堆栈顶部。如果您在此状态下覆盖 onPause() 方法

图 1. 表示任务中的每个新活动如何将项目添加到后台堆栈。当用户按下 Back 按钮时,当前的 Activity 被销毁并恢复之前的 Activity。

图 2. 两个任务:任务 B 在前台接收用户交互,而任务 A 在后台等待恢复。

【讨论】:

在您解释的场景中,Activity 仍在堆栈顶部,但任务本身已转到后台。基本上,用户不再与您的Activity 交互 - 其他一些Activity(来自您自己的任务或来自其他一些)已经出现在前面。这就是公认的答案试图解释的内容。【参考方案4】:

我想我记得在早期版本的 Android 生命周期中,当没有显示任何活动时调用 onPause。即,如果您的一些活动在弹出窗口下仍然可见,则不会调用 onPause。

也许其他一些专家可以为这种行为担保?

【讨论】:

如果没有Activity 显示,则有关onPause() 被调用的位 - 这通常是正确的,但并非严格如此。例如,当您拉下通知栏以使其完全遮挡您的 Activity 时,onPause() 仍然被调用。【参考方案5】:

在我有点奇怪的经历中,onResumedialog.setCanceledOnTouchOutside(true); 调用,但 onPause 永远不会被调用。

话虽如此,我认为文档可能侧重于系统对话框(例如电池电量不足)。

【讨论】:

【参考方案6】:

@hackbot

onPause() 在您的活动不再位于活动>堆栈的顶部时调用。 Dialog 本身不是 Activity,因此不会替换当前栈顶的 >Activity,因此不会导致任何暂停。

一切都取决于实现......

什么是对话框?是WindowManager添加到Display中的一个Window/// 所以它显示的窗口在所有东西的顶部......(Z顺序)

什么是activity...是“事物”,它也创建了它的窗口....

当显示一个对话框或它的窗口在现有活动之上可见时,它会覆盖部分活动窗口,因此 现有活动将移动到部分不可见状态,您将从 ActivityThread 调用 onPause()

但可以肯定的是,我们还需要在这里考虑一个想法......

如果是显示在顶部的独立窗口它是子窗口并且它的父窗口是活动窗口,则窗口的状态。... p>

所以当我们知道时

我们用来添加的 Window.LayoutParams (FLAGS) 以及 IBinder 用于窗口显示的内容

我们将了解当窗口相互重叠显示时 Activity 的行为方式......因为 每个窗口都有一个回调它们被 Activity 或对话框用来管理它们的状态......

涉及的组件:

android.os.IBinder

android.view.Window

android.view.Window.Callback

android.view.WindowManager

android.view.WindowManager.LayoutParams

android.view.Display

顺便说一句:

如果您想知道屏幕上的窗口 [仅适用于您拥有的进程 - 因为窗口属于进程并且这些是沙盒的 - 每个进程都是一个单独的 JVM,严格来说是“ART”],您可以使用 replection 请参阅:

android.view.WindowManagerImpl android.view.WindowManagerGlobal

【讨论】:

【参考方案7】:

onPause() 每次当 Activity 进入后台并且 Dialog 或其他 Activity 进入前台时调用。这样做是为了优先考虑用户正在与之交互的事物。例如:假设您在应用程序的 homescreen(这又是一个活动)中,则 homescreen 被称为在 foreground 中。当您通过按某个按钮或对话框进入下一个屏幕时,下一个 screen/Activity/Dialog 会出现在 foreGroundhomecreen 进入背景,这只是意味着 homeScreen's @ 987654327@ 方法被调用。

【讨论】:

好吧,另一个 Activity 出现在前台的情况是显而易见的。我对文档声称出现对话框时调用onPause() 感到困惑。我已经用代码编辑了我的问题,解释了我认为文档声称的内容,但我没有看到发生。 @techie.curious..是的,你可能是对的。它仅在 Activity 转换时发生,而不是在创建对话框时发生。我现在检查了它。

以上是关于Android:在啥情况下出现对话框会导致 onPause() 被调用?的主要内容,如果未能解决你的问题,请参考以下文章

memcpy在啥情况下会失败

React:useState 钩子中的 setState 在啥情况下会导致重新渲染?

Linux信号函数的SIG_ERR在啥情况下会出现?

在啥情况下 viewWillAppear 会被调用?

arcgis空间参考修改在啥情况下无法完成

oracle表在啥情况下会被锁住