Activity
会被重新启动(调用onCreate
)。现在,这可能是预期的行为,但我在onCreate
方法中进行了很多初始设置,因此我需要:
- 将所有初始设置放在另一个函数中,以便设备旋转时不会丢失它们。
- 使
onCreate
不再被调用,仅调整布局。 - 将应用限制为仅支持竖屏模式,这样就不会调用
onCreate
。
Activity
会被重新启动(调用onCreate
)。现在,这可能是预期的行为,但我在onCreate
方法中进行了很多初始设置,因此我需要:
onCreate
不再被调用,仅调整布局。onCreate
。根据您在初始化过程中所做的操作,您可以考虑创建一个扩展了Application
类的新类,并将初始化代码移动到该类中重写的onCreate
方法中。
class MyApplicationClass: Application {
@override fun onCreate() {
super.onCreate()
// Put your application initialization code here
}
}
public class MyApplicationClass extends Application {
@Override
public void onCreate() {
super.onCreate();
// Put your application initialization code here
}
}
应用程序类中的onCreate
方法只在整个应用程序创建时调用,因此方向或键盘可见性更改导致的活动重新启动不会触发它。
最好将此类的实例公开为单例并使用getter和setter公开正在初始化的应用程序变量。
注意:您需要在清单中指定新应用程序类的名称以进行注册和使用:
<application
android:name="com.you.yourapp.MyApplicationClass"
更新:自API 13起已弃用;请参阅推荐的替代方法
作为另一种选择,您可以让应用程序监听会导致重启的事件,例如方向和键盘可见性更改,并在Activity内处理它们。
首先,在Activity的清单节点中添加android:configChanges
节点:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
或者对于Android 3.2(API级别13)及更高版本:
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name">
然后在Activity中重写onConfigurationChanged
方法,并调用setContentView
来强制重新绘制新方向的GUI布局。
@override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
setContentView(R.layout.myLayout)
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}
android:configChanges
。它应该只作为最后的手段来使用。请参阅 "处理运行时更改" 以获取有关如何正确处理由于配置更改而重新启动的详细信息。相反,为了在旋转事件中保留数据,他们似乎更喜欢使用 onSaveInstanceState Bundle
。或者就像 @Jon-O 提到的,使用 onRetainNonConfigurationInstance
。 - Goffredoandroid:configChanges
能够让我省下很多工作量,所以我不喜欢谷歌告诉我只有在万不得已的情况下才使用它,而不解释为什么。请给我一个理由不去省下大量的工作量。 - NilzorAndroid 3.2及以上版本更新提示:
注意:从Android 3.2(API level 13)开始,当设备在纵横屏方向之间切换时,"屏幕尺寸(screen size)"也会发生改变。因此,如果您想要防止在开发API级别为13或更高(由minSdkVersion和targetSdkVersion属性声明)的应用程序时,由于方向更改而导致运行时重新启动,则必须除了包含"orientation"值外,还要包含"screenSize"值。也就是说,您必须声明
android:configChanges="orientation|screenSize"
。然而,如果您的应用程序目标是API级别12或更低,则您的活动始终会自己处理此配置更改(即使在运行Android 3.2或更高版本的设备上,此配置更改也不会重新启动您的活动)。
Fragments
和 setRetainInstance
代替。 - Simon ForsbergscreenSize
适用于 Android 3.2 及更高版本,这解决了我的问题,谢谢! - fantouch不要试图完全停止触发 onCreate()
,而是可以尝试检查传递给该事件的 Bundle
savedInstanceState
是否为null。例如,如果我有一些逻辑只应在 Activity
真正创建时运行,而不是在每次方向更改时运行,则只有在 savedInstanceState
为null时,我才在 onCreate()
中运行该逻辑。
否则,我仍希望布局能够正确地重绘以适应方向的更改。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list);
if(savedInstanceState == null){
setupCloudMessaging();
}
}
我不确定这是否是最终答案,但它对我有用。
Intent serverintent = new Intent(MainActivity.this, MessageListener.class);
和startService(serverintent);
创建一个serverSocket = new ServerSocket(0xcff2);
,然后使用BufferedReader(new InputStreamReader(client.getInputStream()))
接受Socket client = serverSocket.accept();
,即使旋转了我的Android设备也能保持客户端/服务器连接处于活动状态,同时保持GUI旋转。根据手册,当最后一个活动被关闭时savedInstanceState
会被初始化。 - Fred F我所做的是...
在清单文件中,添加到活动部分:
android:configChanges="keyboardHidden|orientation"
在实现活动的代码中:
//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();
}
你所描述的是默认行为。你需要通过添加以下代码来检测和处理这些事件:
android:configChanges
将你想要处理的更改添加到清单中。因此,对于定位,您将使用:
android:configChanges="orientation"
如果要检测键盘是否打开或关闭,可以使用以下代码:
android:configChanges="keyboardHidden"
如果你想同时处理它们,你可以用管道命令将它们分开,例如:
android:configChanges="keyboardHidden|orientation"
这将触发调用的 Activity 中的 onConfigurationChanged 方法。如果你重写了该方法,你可以传入新的值。
希望对你有所帮助。
我刚刚发现了这个技巧:
为了在屏幕方向改变时保持 Activity 的生命周期并通过 onConfigurationChanged
来处理它,文档 和 上面的代码示例 建议在 Manifest 文件中添加以下内容:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
使用这种方式的附加好处是它总是有效的。
额外的秘诀是,省略keyboardHidden
可能看起来很合理,但它会导致模拟器出现故障(至少对于Android 2.1):仅指定orientation
有时会导致模拟器调用OnCreate
和onConfigurationChanged
,而其他时候仅调用OnCreate
。
我没有在设备上看到过这种故障,但我听说其他人在模拟器上也遇到了类似问题。因此,值得记录。
您也可以考虑使用Android平台跨屏幕旋转持久化数据的方法:onRetainNonConfigurationInstance()
和 getLastNonConfigurationInstance()
。
这可以让您在屏幕方向改变时持久保存数据,比如从服务器获取的信息或者在onCreate
或之后计算出来的数据,同时允许Android使用当前屏幕方向的xml文件重新布局Activity
。
需要注意的是,尽管这些方法仍然比大多数以上提到的解决方案更加灵活,但它们现已被弃用,推荐每个想要保留的Fragment
都使用setRetainInstance(true)
并切换到使用Fragments
来处理屏幕旋转。
这种方法在使用Fragment时是有用的,但存在不完整的问题。
通常情况下,当配置发生变化时,Fragments会重新创建。如果你不希望发生这种情况,请在Fragment的构造函数中使用 setRetainInstance(true);
。
这将导致Fragment在配置更改期间保持不变。
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
setRetainInstance()
方法明确告诉Android不要销毁Fragment。 - brianmearns我只是简单地添加了:
android:configChanges="keyboard|keyboardHidden|orientation"
我在AndroidManifest.xml
文件中没有添加onConfigurationChanged
方法到我的活动中。
所以每次键盘滑出或滑入时都不会发生任何事情!还可以查看这篇关于此问题的文章。
onCreate
方法在 Android 设备改变 屏幕方向
时仍然被调用。因此,把所有重要的功能都移动到这个方法中并不能帮助你。