4

进入和退出睡眠模式时,我在 Nexus 5 上有一个奇怪的行为。它以一种非常奇怪的方式杀死并重新启动应用程序。我给你看日志:

进入睡眠模式(按下电源按钮)

17.005: E/MotherActivity(28940): onPause 调用
17.025: E/MotherActivity(28940): onStop 调用
17.315: E/MotherActivity(28940): onDestroy 调用
17.365: E/GameTuto1Activity(28940): MainActivity 构造函数调用
17.365: E/MotherActivity (28940): onCreate 调用
17.695: E/MotherActivity(28940): onStart 调用
17.705: E/MotherActivity(28940): onResume 调用
17.705: E/MotherActivity(28940): onPause 调用

解锁手机时从睡眠模式恢复

755: E/MotherActivity(28940): onResume 调用
935: E/MotherActivity(28940): onPause 调用
935: E/MotherActivity(28940): onStop 调用

然后电话被冻结,直到我终止该过程。但是为什么我在恢复我的应用程序(从睡眠模式回来)时要经历 onPause 和 onStop 以及为什么在进入睡眠模式时 onCreate,OnStart,onResume,onPause ?

如果我对 Nexus7 做同样的事情,它就不会发生,生命周期是“正常的”。下面的日志:

进入睡眠模式(按下电源按钮)

43.782: E/MotherActivity(19876): onPause 调用 43.822: E/MotherActivity(19876): onStop 调用

解锁手机时从睡眠模式恢复

50.142: E/MotherActivity(19876): onRestart 调用 50.142: E/MotherActivity(19876): onStart 调用 50.172: E/MotherActivity(19876): onResume 调用

这个问题很奇怪而且杂乱无章(也许),但答案可能非常聪明。所以,如果你有一个想法?它只发生在我有 3 个线程的项目中:2 个循环线程(我在 onPause 中杀死)和一个由 PoolExecutor 管理的线程(也在 onPause 中杀死)。如果我做一个简单的应用程序,它不会被复制。Nexus5 version=4.4.2, nexus7 version=4.2.2
我知道,那个问题没有代码,我不能分享我的项目。
但提前感谢所有会考虑这个问题的人。
Mathias .... 5 小时后:导致答案......在我的活动清单中,我有:

<activity  
        android:name=".MainActivity"  
        android:label="@string/title_activity_main"  
        **android:screenOrientation="landscape"**
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >  
        <intent-filter>  
        <action android:name="android.intent.action.MAIN" />  
            <category android:name="android.intent.category.LAUNCHER" />  
        </intent-filter>  
    </activity>  

如果我删除 android:screenOrientation="landscape" 它就可以正常工作。那么关于为什么会发生这种情况的任何想法?为什么我不能将我的方向设置为横向并忘记了 configurationChange 事件。
最糟糕的是,如果我听到方向配置发生了变化:

android:configChanges="orientation"

没有调用 onConfigurationChanged 方法!!!但如果我使用: android:configChanges="orientation|screenSize" 并覆盖 onConfiguration 它可以工作....

为什么实际上 screenOrientation=landscape 无法处理 screenSize 配置更改。有没有另一种干净的方法来处理这种混乱,只是对系统说,“伙计,我处于横向模式,当我将手机置于睡眠模式时,不要把我拧成纵向”。
如果这里有人知道,谢谢您的回答。

否则,这意味着如果您希望您的应用程序是纵向或横向的,您需要在清单中添加 android:configChanges="orientation|screenSize" 并覆盖 Activity 中的 onConfigurationChanged(什么都不做)。哦哦'

4

1 回答 1

3

所以这个错误是由于方向改变......但不是真的。实际上,当 Nexus 5 进入睡眠模式并且您的活动处于纵向时,它不是“方向”更改(在我的情况下)而是“屏幕大小更改”作为 configurationChange 事件触发。它不会在 Nexus 7 上发生,因为它的正常模式在进入睡眠状态时是横向的,因此不会触发 configurationChange。

解决方案
这意味着,在 HoneyComb 之后(因为 screenSize 已经开始被 HC 使用),如果在你的清单中,你正在使用

 android:screenOrientation="landscape"

您还需要在清单中包含以下这一行:

 android:configChanges="orientation|screenSize"

在您的 MotherActivity (由您的活动继承的活动)或您的活动中,您必须覆盖配置更改方法,这样:

 /*
 * (non-Javadoc)
 * @see android.app.Activity#onConfigurationChanged(android.content.res.Configuration)
 */
@Override
public void onConfigurationChanged(Configuration newConfig) {
    Log.e("MotherActivity", "onConfigurationChanged called ");
    // this method is there to ensure no configuration changes when going to sleep mode
    // because the device wants my app to go on portrait and then fire screenSize changes
    // sometime some montainview code sucks
    super.onConfigurationChanged(newConfig);
    // and of course do nothing !!!
}

可以在这里查看以更好地了解 onConfigurationChange 以及如何处理它。@ http://developer.android.com/guide/topics/resources/runtime-changes.html

回到我的问题
在我的情况下,由于没有预期的配置更改,我正在与丢失的线程作斗争。
简单技巧 n°1
因此,避免这种痛苦并快速检测到它的简单技巧是在开发模式下将日志添加到您的母亲活动中。因此,在测试时,您始终拥有活动生命周期的日志。它将帮助您避免生命周期混乱。
示例:

/*
 * (non-Javadoc)
 * @see android.app.Activity#onCreate(android.os.Bundle)
 */
@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.e("MotherActivity", "onCreate called");
    super.onCreate(savedInstanceState);
}

线程法则
最后,我的意思是,始终深入了解您的线程(如果有的话)并确保没有内存泄漏(线程必须死掉)并确保您的线程被保留(onRetainNonConfigurationInstance 或使用不带GUI 和 setRetainInstance(true)) 当配置更改或确保处理配置更改时。
简单技巧 n°2
另一个技巧也是监听 mcc 和 mnc(在您的清单 android:configChanges="orientation|screenSize|mcc|mcn" 中),因为您的应用程序大部分时间都不关心更改电信运营商。而且大多数时候你没有测试那个案例。

祝大家有个愉快的一天!

于 2014-04-02T07:01:26.923 回答