OnPause 和 OnStop() 在开始活动后立即调用 [英] OnPause and OnStop() called immediately after starting activity

查看:26
本文介绍了OnPause 和 OnStop() 在开始活动后立即调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个活动需要在启动时打开(如果关闭)屏幕.所以在onCreate中,我有:

I have an activity that needs to turn screen on(if offed) when it is started. So in onCreate, I have:

this.getWindow().setFlags(
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

在广播接收器中使用唤醒锁的帮助下,我能够在从广播接收器启动时显示我的活动.

Using this with help of wakelock in broadcasr receiver , I am able to cause my activity to display whenever it is started from broadcast receiver.

但是问题很奇怪,activity生命周期就是这样调用的,onPause()和onResume在activity启动后立即调用

But problem is very strange, activity lifecycle calls in this manner, onPause() and onResume immediately after starting activity

  1. onCreate
  2. 启动
  3. onResume
  4. 暂停
  5. 停止
  6. 启动
  7. onResume

<小时>

所以问题出在开始和恢复调用两次,在停止时也调用,我想在 onStop() 中实现一些逻辑,但是这样的行为应用程序将无法正常工作.


So the problem is on start and on resume calling twice, with on stop also calling, I want to implement some logic in onStop() but, with such behavior app will not work correctly.

编辑

我发现问题只是由于标志 FLAG_SHOW_WHEN_LOCKED.当设备被锁定时.并且只有在活动开始之前设备被锁定时才会发生.

I found problem is only due to flag FLAG_SHOW_WHEN_LOCKED. and when device is locked. and it only happens when device is locked before activity is starting.

P.S 我正在使用带有广播接收器的警报管理器,然后从广播接收器开始活动.

P.S I am using alarm manager with broadcast receiver, and then starts activity from broadcast receiver.

推荐答案

  • 让我们了解为什么多次调用生命周期方法.
  • 这是ActivityThread,负责执行应用进程的Activity.

    Here is an important code comment documented in ActivityThread, which is responsible for executing the activities of the application process.

    我们通过正常启动来实现这一点(因为活动期望在第一次运行时通过 onResume(),在他们的窗口显示之前),然后暂停它.

    We accomplish this by going through the normal startup (because activities expect to go through onResume() the first time they run, before their window is displayed), and then pausing it.

    紧接在onResume 之后,活动窗口被附加到窗口管理器并调用onAttachedtoWindow.如果屏幕打开,则活动窗口将获得焦点,并使用 true 参数调用 onWindowFocusChanged.来自文档:

    Right after onResume, the activity window is attached to the window manager and onAttachedtoWindow is invoked. If the screen is on, the activity window will get focus and onWindowFocusChanged is invoked with true parameter. From docs:

    请记住,onResume 并不是您的最佳指标活动对用户可见;系统窗口,例如键盘锁可能在前面.使用 onWindowFocusChanged(boolean) 来确定您的活动对用户可见

    Keep in mind that onResume is not the best indicator that your activity is visible to the user; a system window such as the keyguard may be in front. Use onWindowFocusChanged(boolean) to know for certain that your activity is visible to the user

    在报告的问题中,屏幕如果关闭.因此活动窗口不会获得焦点,这导致活动的 onPause 方法被调用,然后是 onStop 方法,因为活动窗口不可见.

    In the reported issue, the screen if off. Hence activity window will not get focus, which results in activity's onPause method getting called followed by onStop method, as the activity window is not visible.

    由于在活动窗口上设置了 WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON 标志,因此窗口管理器服务使用电源管理器 api 打开屏幕.以下是 WindowManagerService 代码:

    Since WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON flag is set on activity window, the window manager service turns on the screen using power manager api. Following is the WindowManagerService code:

    public int relayoutWindow(...) {
        ...
        toBeDisplayed = !win.isVisibleLw();
        ...
        if (toBeDisplayed) {
            ...
            if ((win.mAttrs.flags
                & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
                if (DEBUG_VISIBILITY) Slog.v(TAG,
                    "Relayout window turning screen on: " + win);
                    win.mTurnOnScreen = true;
                }
            ...
            if (mTurnOnScreen) {
                if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
                mPowerManager.wakeUp(SystemClock.uptimeMillis());
                mTurnOnScreen = false;
            }
            ...
    }
    

    屏幕打开后,onStartonPause 被再次调用.

    After the screen turns on onStart and onPause are called again.

    因此:onCreate - onStart - onResume - onPause - onStop - onStart - onPause.

    这可以通过使用adb 命令或eclipse 锁定设备并启动活动来验证.

    This can be verified by locking the device and starting the activity using adb command or eclipse.

    • 理想的解决方案

    如果你在 onCreate 中开始一个任务,你需要在 onDestory 中停止它(如果任务仍然挂起).类似地,对于 onStart,它将是 onStop,对于 onResume,它将是 onPause.

    If you start a task in onCreate you need to stop it in onDestory (if the task is still pending). Similarly for onStart it would be onStop and for onResume it would be onPause.

    • 解决方法

    如果你不能按照上面的协议,你可以使用hasWindowFocusonPause 方法中.通常,onPause 中的活动窗口焦点状态将为真.在屏幕关闭或屏幕打开并显示键盘锁的情况下,onPause 中的活动窗口焦点将为假.

    If you can't follow the above protocol, you can check the status of activity window focus using hasWindowFocus in onPause method. Normally the activity window focus status will be true in onPause. In scenarios like screen is off or screen is on with keyguard displayed, the activity window focus will be false in onPause.

    boolean mFocusDuringOnPause;
    
    public void onPause() {
        super.onPause;
    
        mFocusDuringOnPause = hasWindowFocus();    
    }
    
    public void onStop() {
        super.onStop();
    
        if(mFocusDuringOnPause) {
            // normal scenario
        } else {
            // activity was started when screen was off / screen was on with keygaurd displayed
        }
    }
    

    这篇关于OnPause 和 OnStop() 在开始活动后立即调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆