Nexus 5进入睡眠模式导致活动的生命周期出现问题

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版本=4.4.2,nexus7版本=4.2.2 我知道,这个问题中没有代码,我无法分享我的项目。 但是提前感谢所有思考这个问题的人。 Mathias .... 五小时后: 答案的线索 ...... 在我的清单中,我的活动上有:

<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",它就能正常工作。 那么这是为什么呢?为什么我不能设置横向方向并忘记配置更改事件。
更糟糕的是,如果我监听方向配置更改:

android:configChanges="orientation"

onConfigurationChanged方法没有被调用!!!但是如果我使用: android:configChanges="orientation|screenSize" 并重写onConfiguration,它就可以工作了....

为什么,屏幕方向=横向不能处理屏幕尺寸配置更改。有没有另一种简洁的方法来处理这个混乱,并告诉系统,“伙计,我处于横向模式,请不要在我把手机放入睡眠模式时将我弄成纵向”。
如果这里有人知道,谢谢回答。

否则,这意味着如果您想使应用程序为纵向或横向,则需要在清单中添加android:configChanges="orientation|screenSize",并在Activity中重写onConfigurationChanged(什么也不做)。oO'


我曾经遇到过同样的问题,看看我的解决方案:http://stackoverflow.com/a/18018298/2001247 ... 不过可能不是你所期望的 :) - ElDuderino
谢谢,但是方向变化很混乱。 - Mathias Seguy Android2ee
1个回答

3
所以这个错误是由于屏幕大小改变导致的…但实际上并不完全是由于“方向”变化 (在我的情况下),而是由于当Nexus 5进入睡眠模式且您的活动处于纵向状态时,触发了被配置更改事件所触发的“屏幕大小改变”。在Nexus 7上没有发生这种情况,因为它的正常模式是横向的,所以不会触发配置更改。 解决方案
这意味着,在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
所以一个简单的技巧是避免这种痛苦并快速检测到它,就是在dev模式下将Log添加到您的Mother activity中。因此,在测试时,您始终拥有您的活动生命周期的日志记录。它将帮助您避免生命周期混乱。
例如:

/*
 * (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)),或确保处理配置更改。
简单技巧2
另一个技巧是还要注意mcc和mnc(在你的清单中android:configChanges="orientation | screenSize | mcc | mcn"),因为你的应用程序大多数情况下不关心电信运营商的更改。而且大多数时候你也没有测试过那种情况。

祝大家有个愉快的一天!


在我的HTC One (M7)双卡手机上,使用Android API 4.4也发现了同样的问题。您的解决方案是完全正确的。清单中的一个字符串和主活动中的onConfigurationChanged方法可以解决问题。 - Dimon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接