Android屏幕旋转导致活动重启

1459
在我的Android应用中,当我旋转设备(推出键盘)时,我的Activity会被重新启动(调用onCreate)。现在,这可能是预期的行为,但我在onCreate方法中进行了很多初始设置,因此我需要:
  1. 将所有初始设置放在另一个函数中,以便设备旋转时不会丢失它们。
  2. 使onCreate不再被调用,仅调整布局。
  3. 将应用限制为仅支持竖屏模式,这样就不会调用onCreate

4
这篇博客文章中详细解释了如何在活动组件配置更改时保留长时间运行的异步任务,点击此处阅读。 - Adrian Monk
3
这不是一个直接的答案,因为其他人已经回答了,但我邀请您查看LogLifeCycle,以了解您的Android应用程序在生命周期方面发生了什么。 - Snicolas
34个回答

21

将下面的代码放入你的 <activity> 标签中的 Manifest.xml 文件中:

android:configChanges="screenLayout|screenSize|orientation"

20

非常简单,只需按照以下步骤进行:

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

这对我有效:

注意:方向取决于您的要求


19
onConfigurationChanged is called when the screen rotates. 
(onCreate is no longer called when the screen rotates due to manifest, see:  
android:configChanges)

清单文件中的哪一部分告诉它“不要调用onCreate()”?

此外,Google的文档建议避免使用android:configChanges(除非迫不得已)。但是他们建议的替代方法都使用android:configChanges

我的经验是,在旋转时模拟器总是会调用onCreate()。但是我在运行相同代码的1-2台设备上...没有这种情况。 (不确定为什么会有任何差异。)


17

需要在Android清单文件中进行以下更改:

android:configChanges="keyboardHidden|orientation" 

在活动中需要添加的内容有:

public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

17

将此行添加到您的清单中:-

android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

并将这段代码片段添加到活动中:

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

16

有几种方式可以实现这个:

保存Activity状态

您可以在onSaveInstanceState中保存活动状态。

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example: outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

然后使用bundle来恢复状态。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

自己处理屏幕方向变化

另一种选择是自己处理屏幕方向的变化。但这不被认为是一种良好的做法。

将以下内容添加到你的清单文件中。

android:configChanges="keyboardHidden|orientation"

适用于 Android 3.2 及更高版本:

android:configChanges="keyboardHidden|orientation|screenSize"

@Override
public void onConfigurationChanged(Configuration config) {
    super.onConfigurationChanged(config);
    
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portrait mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

限制旋转

您也可以将您的活动限制为纵向或横向模式,以避免旋转。

在清单文件中的活动标签中添加以下内容:

        android:screenOrientation="portrait"

或在您的活动中以编程方式实现:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

12
我发现实现这个的方法是使用onRestoreInstanceStateonSaveInstanceState事件将一些东西保存到Bundle中(即使您不需要保存任何变量,也要在里面放入一些东西,以便Bundle不为空)。然后,在onCreate方法中,检查Bundle是否为空,如果是,则进行初始化,否则就不需要。

12

虽然这不是“安卓方式”,但通过手动处理方向变化并简单地重新定位视图中的小部件以考虑改变的方向,我已经获得了非常好的结果。这比任何其他方法都更快,因为视图不需要保存和恢复。它还为用户提供了更无缝的体验,因为重新定位的小部件完全相同,只是移动和/或调整大小。不仅可以以这种方式保存模型状态,还可以保留视图状态。

RelativeLayout有时可以成为一个不错的选择,用于在不同时间重新调整自身的视图。您只需为每个子小部件提供一组纵向布局参数和一组横向布局参数,并在每个参数集上使用不同的相对定位规则。然后,在您的 onConfigurationChanged() 方法中,您将适当的参数传递给每个子项的 setLayoutParams() 调用。如果任何子控件本身需要进行内部重新定位,则只需调用该子控件上的方法执行重新定位。该子控件在需要内部重新定位的任何子控件上同样调用方法,依此类推。


我很想看看这方面的一些示例代码,似乎非常棒! - Henrique de Sousa

10
每次屏幕旋转时,打开的活动被结束并调用了onCreate()。
1. 你可以在屏幕旋转时保存活动状态,这样当活动的onCreate()再次被调用时,就可以恢复所有旧的内容。请参考这个链接。 2. 如果你想防止活动重新启动,只需在你的manifest.xml文件中添加以下代码。
<activity android:name=".Youractivity"
    android:configChanges="orientation|screenSize"/>

8

您需要使用onSavedInstanceState方法将所有值存储到其参数中,该参数是一个bundle。

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

并使用

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

用于检索和设置视图对象的值,它将处理屏幕旋转。


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