旋转Android时重新启动活动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/456211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:10:21  来源:igfitidea点击:

Activity restart on rotation Android

androidrotationandroid-activity

提问by Isaac Waller

In my Android application, when I rotate the device (slide out the keyboard) then my Activityis restarted (onCreateis called). Now, this is probably how it's supposed to be, but I do a lot of initial setting up in the onCreatemethod, so I need either:

在我的 Android 应用程序中,当我旋转设备(滑出键盘)时,我的设备Activity会重新启动(onCreate被调用)。现在,这可能是它应该的样子,但我在onCreate方法中做了很多初始设置,所以我需要:

  1. Put all the initial setting up in another function so it's not all lost on device rotation or
  2. Make it so onCreateis not called again and the layout just adjusts or
  3. Limit the app to just portrait so that onCreateis not called.
  1. 将所有初始设置放在另一个函数中,这样就不会在设备旋转或
  2. 使它onCreate不再被调用并且布局只是调整或
  3. 将应用程序限制为仅纵向,这样onCreate就不会被调用。

采纳答案by Reto Meier

Using the Application Class

使用应用程序类

Depending on what you're doing in your initialization you could consider creating a new class that extends Applicationand moving your initialization code into an overridden onCreatemethod within that class.

根据您在初始化中所做的事情,您可以考虑创建一个新类,该类Application将您的初始化代码扩展并移动到onCreate该类中的重写方法中。

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

The onCreatein the application class is only called when the entire application is created, so the Activity restarts on orientation or keyboard visibility changes won't trigger it.

onCreate创建整个应用程序时在应用程序类只叫,等方向或键盘知名度转变活动重启不会触发它。

It's good practice to expose the instance of this class as a singleton and exposing the application variables you're initializing using getters and setters.

将此类的实例作为单例公开并公开使用 getter 和 setter 初始化的应用程序变量是一种很好的做法。

NOTE: You'll need to specify the name of your new Application class in the manifest for it to be registered and used:

注意:您需要在清单中指定新应用程序类的名称,以便注册和使用它:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Reacting to Configuration Changes[UPDATE: this is deprecated since API 13; see the recommended alternative]

对配置更改做出反应[更新:自 API 13 以来已弃用;查看推荐的替代方案]

As a further alternative, you can have your application listen for events that would cause a restart – like orientation and keyboard visibility changes – and handle them within your Activity.

作为进一步的选择,您可以让您的应用程序侦听会导致重新启动的事件(例如方向和键盘可见性更改),并在您的 Activity 中处理它们。

Start by adding the android:configChangesnode to your Activity's manifest node

首先将android:configChanges节点添加到您的活动的清单节点

 <activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"
      android:label="@string/app_name">

or for Android 3.2 (API level 13) and newer:

或适用于Android 3.2(API 级别 13)及更新版本

<activity android:name=".MyActivity"
      android:configChanges="keyboardHidden|orientation|screenSize"
      android:label="@string/app_name">

Then within the Activity override the onConfigurationChangedmethod and call setContentViewto force the GUI layout to be re-done in the new orientation.

然后在 Activity 中覆盖该onConfigurationChanged方法并调用setContentView以强制在新方向上重新完成 GUI 布局。

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}

回答by Gorm

Update for Android 3.2 and higher:

Android 3.2 及更高版本的更新:

Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changeswhen the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize"value in addition to the "orientation"value. That is, you must declare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).

注意:从 Android 3.2(API 级别 13)开始,当设备在纵向和横向之间切换时,“屏幕尺寸”也会发生变化。因此,如果在为 API 级别 13 或更高级别(如 minSdkVersion 和 targetSdkVersion 属性所声明的)进行开发时,要防止由于方向更改而导致运行时重新启动"screenSize",则除了该"orientation"值之外,还必须包括该值。也就是说,您必须声明android:configChanges="orientation|screenSize". 但是,如果您的应用程序面向 API 级别 12 或更低级别,则您的 Activity 始终会自行处理此配置更改(此配置更改不会重新启动您的 Activity,即使在 Android 3.2 或更高版本的设备上运行时)。

回答by nebulae

Instead of trying to stop the onCreate()from being fired altogether, maybe try checking the BundlesavedInstanceStatebeing passed into the event to see if it is null or not.

与其试图完全阻止onCreate()被触发,BundlesavedInstanceState不如尝试检查传递到事件中的事件以查看它是否为空。

For instance, if I have some logic that should be run when the Activityis truly created, not on every orientation change, I only run that logic in the onCreate()only if the savedInstanceStateis null.

例如,如果我有一些逻辑应该在Activity真正创建时运行,而不是在每次方向更改时运行,我只onCreate()savedInstanceState为空时才运行该逻辑。

Otherwise, I still want the layout to redraw properly for the orientation.

否则,我仍然希望布局为方向正确重绘。

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

not sure if this is the ultimate answer, but it works for me.

不确定这是否是最终答案,但它对我有用。

回答by Someone Somewhere

what I did...

我做了什么...

in the manifest, to the activity section, added:

在清单中,到活动部分,添加:

android:configChanges="keyboardHidden|orientation"

in the code for the activity, implemented:

在活动的代码中,实现了:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

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

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}

回答by GregD

What you describe is the default behavior. You have to detect and handle these events yourself by adding:

您所描述的是默认行为。您必须通过添加以下内容来自己检测和处理这些事件:

android:configChanges

to your manifest and then the changes that you want to handle. So for orientation, you would use:

到您的清单,然后是您要处理的更改。因此,对于定位,您将使用:

android:configChanges="orientation"

and for the keyboard being opened or closed you would use:

对于打开或关闭的键盘,您将使用:

android:configChanges="keyboardHidden"

If you want to handle both you can just separate them with the pipe command like:

如果您想同时处理两者,您可以使用管道命令将它们分开,例如:

android:configChanges="keyboardHidden|orientation"

This will trigger the onConfigurationChanged method in whatever Activity you call. If you override the method you can pass in the new values.

这将在您调用的任何活动中触发 onConfigurationChanged 方法。如果覆盖该方法,则可以传入新值。

Hope this helps.

希望这可以帮助。

回答by Liudvikas Bukys

I just discovered this lore:

我刚刚发现了这个传说:

For keeping the Activity alive through an orientation change, and handling it through onConfigurationChanged, the documentationand the code sample abovesuggest this in the Manifest file:

为了通过方向更改保持 Activity 活动并通过 处理它onConfigurationChanged,上面的文档代码示例在 Manifest 文件中建议了这一点:

<activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"
      android:label="@string/app_name">

which has the extra benefit that it always works.

这有一个额外的好处,那就是它总是有效。

The bonus lore is that omitting the keyboardHiddenmay seem logical, but it causes failures in the emulator (for Android 2.1 at least): specifying only orientationwill make the emulator call both OnCreateand onConfigurationChangedsometimes, and only OnCreateother times.

奖金绝杀是省略keyboardHidden似乎合乎逻辑,但它(至少为Android 2.1)导致的故障在模拟器:只有指定orientation将使模拟器呼叫都OnCreateonConfigurationChanged有时,只有OnCreate其他时间。

I haven't seen the failure on a device, but I have heard about the emulator failing for others. So it's worth documenting.

我还没有在设备上看到失败,但我听说过其他人的模拟器失败。所以值得记录。

回答by Jon O

You might also consider using the Android platform's way of persisting data across orientation changes: onRetainNonConfigurationInstance()and getLastNonConfigurationInstance().

您还可以考虑使用 Android 平台的跨方向更改持久化数据的方式: onRetainNonConfigurationInstance()getLastNonConfigurationInstance().

This allows you to persist data across configuration changes, such as information you may have gotten from a server fetch or something else that's been computed in onCreateor since, while also allowing Android to re-layout your Activityusing the xml file for the orientation now in use.

这允许您跨配置更改保留数据,例如您可能从服务器获取的信息或在其中onCreate或之后计算的其他内容,同时还允许 Android 重新布局您Activity使用的方向的 xml 文件现在正在使用.

See hereor here.

请参阅此处此处

It should be noted that these methods are now deprecated (although still more flexible than handling orientation change yourself as most of the above solutions suggest) with the recommendation that everyone switch to Fragmentsand instead use setRetainInstance(true)on each Fragmentyou want to retain.

应该注意的是,这些方法现在已被弃用(尽管仍然比上述大多数解决方案建议的那样自己处理方向更改更灵活),并建议每个人都切换到Fragments并改为setRetainInstance(true)Fragment您想要保留的每个上使用。

回答by Abdo

The approach is useful but is incomplete when using Fragments.

该方法很有用,但在使用 Fragments 时并不完整。

Fragments usually get recreated on configuration change. If you don't wish this to happen, use

片段通常会在配置更改时重新创建。如果您不希望发生这种情况,请使用

setRetainInstance(true);in the Fragment's constructor(s)

setRetainInstance(true);在片段的构造函数中

This will cause fragments to be retained during configuration change.

这将导致在配置更改期间保留片段。

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

回答by bass.t

I just simply added

我只是简单地添加了

     android:configChanges="keyboard|keyboardHidden|orientation"

in the manifest file and did not addany onConfigurationChangedmethod in my activity.

在清单文件中,并没有onConfigurationChanged在我的活动中添加任何方法。

So every time the keyboard slides out or in nothing happens.

因此,每次键盘滑出或滑入时都没有任何反应

回答by ganesh krishnan

The onCreatemethod is still called even when you change the orientationof android. So moving all the heavy functionality to this method is not going to help you

onCreate即使您更改了orientationandroid的方法,该方法仍会被调用。因此,将所有繁重的功能转移到此方法对您没有帮助