Android 轮流重启 Activity
在我的 Android 应用程序中,当我旋转设备(滑出键盘)时,我的 Activity
将重新启动(onCreate
被调用)。现在,这可能是应该的样子,但我在 onCreate
方法中做了很多初始设置,所以我需要:
- 将所有初始设置放在另一个函数中,这样就不是全部了设备旋转时丢失或
- 使其不会再次调用
onCreate
并且布局仅调整或 - 将应用程序限制为仅纵向,以便不会调用
onCreate
。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
使用应用程序类
根据您在初始化中所做的操作,您可以考虑创建一个扩展
Application
的新类,并将初始化代码移动到该类中重写的onCreate
方法中班级。Kotlin 版本
Java 版本
应用程序类中的
onCreate
仅在创建整个应用程序时调用,因此 Activity 在方向或键盘可见性更改时重新启动不会触发它。最好将此类的实例公开为单例,并公开使用 getter 和 setter 初始化的应用程序变量。
注意:您需要在清单中指定新应用程序类的名称,以便注册和使用它:
对配置更改做出反应
更新:自 API 13 起已弃用; 查看推荐的替代方案
作为进一步的替代方案,您可以让应用程序侦听会导致重新启动的事件(例如方向和键盘可见性更改),并在您的活动中处理它们。
首先将
android:configChanges
节点添加到 Activity 的清单节点:或者对于 Android 3.2(API 级别 13)和更新的:
然后在 Activity 中覆盖
onConfigurationChanged
方法并调用setContentView
强制 GUI 布局在新方向上重新完成。Kotlin 版本
Java 版本
Using the Application Class
Depending on what you're doing in your initialization you could consider creating a new class that extends
Application
and moving your initialization code into an overriddenonCreate
method within that class.Kotlin version
Java version
The
onCreate
in 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.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.
NOTE: You'll need to specify the name of your new Application class in the manifest for it to be registered and used:
Reacting to Configuration Changes
UPDATE: This is deprecated since API 13; see the recommended alternative
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.
Start by adding the
android:configChanges
node to your Activity's manifest node:Or for Android 3.2 (API level 13) and newer:
Then within the Activity override the
onConfigurationChanged
method and callsetContentView
to force the GUI layout to be re-done in the new orientation.Kotlin version
Java version
Android 3.2 及更高版本的更新:
来自 http ://web.archive.org/web/20120805085007/http://developer.android.com/guide/topics/resources/runtime-changes.html
Update for Android 3.2 and higher:
From http://web.archive.org/web/20120805085007/http://developer.android.com/guide/topics/resources/runtime-changes.html
与其尝试完全阻止
onCreate()
被触发,不如尝试检查传递到事件中的Bundle
savedInstanceState
来查看是否它是否为空。例如,如果我有一些逻辑应该在
Activity
真正创建时运行,而不是在每次方向更改时运行,那么我只在onCreate()
中运行该逻辑如果savedInstanceState
为 null。否则,我仍然希望布局能够根据方向正确重绘。
不确定这是否是最终答案,但它对我有用。
Instead of trying to stop the
onCreate()
from being fired altogether, maybe try checking theBundle
savedInstanceState
being passed into the event to see if it is null or not.For instance, if I have some logic that should be run when the
Activity
is truly created, not on every orientation change, I only run that logic in theonCreate()
only if thesavedInstanceState
is null.Otherwise, I still want the layout to redraw properly for the orientation.
not sure if this is the ultimate answer, but it works for me.
我做了什么......
在清单中的活动部分添加:
在活动的代码中,实现:
what I did...
in the manifest, to the activity section, added:
in the code for the activity, implemented:
您所描述的是默认行为。您必须自己检测和处理这些事件,方法是添加:
到您的清单中,然后添加您想要处理的更改。因此,对于方向,您将使用:
对于打开或关闭的键盘,您将使用:
如果您想处理两者,您可以使用管道命令将它们分开,例如:
这将在您调用的任何 Activity 中触发 onConfigurationChanged 方法。如果您重写该方法,则可以传入新值。
希望这有帮助。
What you describe is the default behavior. You have to detect and handle these events yourself by adding:
to your manifest and then the changes that you want to handle. So for orientation, you would use:
and for the keyboard being opened or closed you would use:
If you want to handle both you can just separate them with the pipe command like:
This will trigger the onConfigurationChanged method in whatever Activity you call. If you override the method you can pass in the new values.
Hope this helps.
我刚刚发现了这个知识:
为了通过方向变化保持 Activity 的活动状态,并通过
onConfigurationChanged
处理它,文档 和 上面的代码示例在清单文件中建议了这一点:它的额外好处是它始终有效。
额外的知识是,省略
keyboardHidden
可能看起来合乎逻辑,但它会导致模拟器失败(至少对于 Android 2.1):仅指定orientation
将使模拟器调用两者有时OnCreate
和onConfigurationChanged
,其他时候仅OnCreate
。我还没有在设备上看到过失败,但我听说过其他设备上的模拟器失败。所以值得记录。
I just discovered this lore:
For keeping the Activity alive through an orientation change, and handling it through
onConfigurationChanged
, the documentation and the code sample above suggest this in the Manifest file:which has the extra benefit that it always works.
The bonus lore is that omitting the
keyboardHidden
may seem logical, but it causes failures in the emulator (for Android 2.1 at least): specifying onlyorientation
will make the emulator call bothOnCreate
andonConfigurationChanged
sometimes, and onlyOnCreate
other times.I haven't seen the failure on a device, but I have heard about the emulator failing for others. So it's worth documenting.
您还可以考虑使用 Android 平台在方向变化时保留数据的方式:
onRetainNonConfigurationInstance()
和getLastNonConfigurationInstance()
。这允许您在配置更改期间保留数据,例如您可能从服务器获取获取的信息或在
onCreate
或此后计算的其他内容,同时还允许 Android 重新布局您的Activity
使用 xml 文件作为当前使用的方向。请参阅此处或此处。
应该注意的是,这些方法现在已被弃用(尽管仍然比上面大多数解决方案建议的自己处理方向更改更灵活),建议每个人都切换到
Fragments
并改为使用setRetainInstance (true)
在您想要保留的每个Fragment
上。You might also consider using the Android platform's way of persisting data across orientation changes:
onRetainNonConfigurationInstance()
andgetLastNonConfigurationInstance()
.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
onCreate
or since, while also allowing Android to re-layout yourActivity
using the xml file for the orientation now in use.See here or 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
Fragments
and instead usesetRetainInstance(true)
on eachFragment
you want to retain.该方法很有用,但在使用 Fragment 时并不完整。
片段通常会在配置更改时重新创建。如果您不希望发生这种情况,请
在片段的构造函数中使用
setRetainInstance(true);
这将导致片段在配置更改期间被保留。
http://developer.android.com/reference/android /app/Fragment.html#setRetainInstance(boolean)
The approach is useful but is incomplete when using 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)This will cause fragments to be retained during configuration change.
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
我只是简单地在
AndroidManifest.xml
文件中添加:并且在我的活动中没有添加任何
onConfigurationChanged
方法。所以每次键盘滑出或者什么反应都没有!另请查看此 关于此问题的文章。
I just simply added:
in the
AndroidManifest.xml
file and did not add anyonConfigurationChanged
method in my activity.So every time the keyboard slides out or in nothing happens! Also checkout this article about this problem.
即使你改变了android的
orientation
,onCreate
方法仍然会被调用。因此,将所有繁重的功能转移到此方法不会对您有帮助The
onCreate
method is still called even when you change theorientation
of android. So moving all the heavy functionality to this method is not going to help you将以下代码放入
Manifest.xml
中的
标记内:Put the code below inside your
<activity>
tag inManifest.xml
:这非常简单,只需执行以下步骤:
这对我有用:
注意:方向取决于您的要求
It is very simple just do the following steps:
This works for me :
Note: orientation depends on your requitement
清单的哪一部分告诉它“不要调用
onCreate()
”?还,
Google 的文档表示避免使用
android:configChanges
(除非作为最后的手段)。但他们建议所有的替代方法都使用android:configChanges
。根据我的经验,模拟器总是在旋转时调用
onCreate()
。但我运行相同代码的 1-2 台设备...却没有。
(不知道为什么会有任何差异。)
What part of the manifest tells it "don't call
onCreate()
"?Also,
Google's docs say to avoid using
android:configChanges
(except as a last resort). But then the alternative methods they suggest all DO useandroid:configChanges
.It has been my experience that the emulator ALWAYS calls
onCreate()
upon rotation.But the 1-2 devices that I run the same code on... do not.
(Not sure why there would be any difference.)
在 Android 清单中进行的更改包括:
在 Activity 中进行的添加包括:
Changes to be made in the Android manifest are:
Additions to be made inside activity are:
将此行添加到您的清单中:-
并将此代码段添加到活动中:-
Add this line to your manifest :-
and this snippet to the activity :-
有多种方法可以实现此目的:
保存 Activity 状态
您可以在
onSaveInstanceState
中保存 Activity 状态。然后使用
bundle
恢复状态。自己处理方向变化
另一种选择是自己处理方向变化。但这不被认为是一个好的做法。
将其添加到您的清单文件中。
对于 Android 3.2 及更高版本:
限制旋转
您还可以将活动限制为纵向或横向模式以避免旋转。
将其添加到清单文件中的活动标记中:
或者在您的活动中以编程方式实现此操作:
There are several ways to do this:
Save Activity State
You can save the activity state in
onSaveInstanceState
.and then use the
bundle
to restore the state.Handle orientation changes by yourself
Another alternative is to handle the orientation changes by yourself. But this is not considered a good practice.
Add this to your manifest file.
for Android 3.2 and later:
Restrict rotation
You can also confine your activity to portrait or landscape mode to avoid rotation.
Add this to the activity tag in your manifest file:
Or implement this programmatically in your activity:
我发现执行此操作的方法是使用
onRestoreInstanceState
和onSaveInstanceState
事件在Bundle
中保存某些内容(即使您不需要任何内容)保存的变量,只需在其中放置一些内容,这样Bundle
就不为空)。然后,在onCreate方法中检查Bundle是否为空,如果是,则进行初始化,如果不是,则进行初始化。The way I have found to do this is use the
onRestoreInstanceState
and theonSaveInstanceState
events to save something in theBundle
(even if you dont need any variables saved, just put something in there so theBundle
isn't empty). Then, on theonCreate
method, check to see if theBundle
is empty, and if it is, then do the initialization, if not, then do it.尽管这不是“Android 方式”,但我通过自己处理方向更改并简单地在视图中重新定位小部件以考虑更改后的方向,获得了非常好的结果。这比任何其他方法都要快,因为您不必保存和恢复视图。它还为用户提供了更无缝的体验,因为重新定位的小部件是完全相同的小部件,只是移动和/或调整了大小。不仅模型状态,而且视图状态都可以通过这种方式保存。
对于需要不时重新调整自身方向的视图来说,
RelativeLayout
有时可能是一个不错的选择。您只需为每个子小部件提供一组纵向布局参数和一组横向布局参数,每个参数具有不同的相对定位规则。然后,在onConfigurationChanged()
方法中,将相应的值传递给每个子项的setLayoutParams()
调用。如果任何子控件本身需要内部重新定向,您只需调用该子控件的方法即可执行重新定向。该子控件同样会调用其任何需要内部重新定向的子控件上的方法,等等。Even though it is not "the Android way" I have gotten very good results by handling orientation changes myself and simply repositioning the widgets within a view to take the altered orientation into account. This is faster than any other approach, because your views do not have to be saved and restored. It also provides a more seamless experience to the user, because the respositioned widgets are exactly the same widgets, just moved and/or resized. Not only model state, but also view state, can be preserved in this manner.
RelativeLayout
can sometimes be a good choice for a view that has to reorient itself from time to time. You just provide a set of portrait layout params and a set of landscaped layout params, with different relative positioning rules on each, for each child widget. Then, in youronConfigurationChanged()
method, you pass the appropriate one to asetLayoutParams()
call on each child. If any child control itself needs to be internally reoriented, you just call a method on that child to perform the reorientation. That child similarly calls methods on any of its child controls that need internal reorientation, and so on.每次旋转屏幕时,打开的 Activity 就会完成,并再次调用 onCreate()。
1.您可以做一件事,在屏幕旋转时保存 Activity 的状态,以便在再次调用 Activity 的 onCreate() 时恢复所有旧内容。
请参阅此链接
2 。如果您想防止重新启动活动,只需将以下行放入您的manifest.xml 文件中即可。
Every time when the screen is rotated, opened activity is finished and onCreate() is called again.
1 . You can do one thing save the state of activity when the screen is rotated so that, You can recover all old stuff when the activity's onCreate() is called again.
Refer this link
2 . If you want to prevent restarting of the activity just place the following lines in your manifest.xml file.
您需要使用 onSavedInstanceState 方法将所有值存储到其参数 is has 中,该参数是一个包
,并用于
检索和设置值以查看对象
它将处理屏幕旋转
you need to use the onSavedInstanceState method to store all the values to its parameter is has which is a bundle
and use
to retrieve and set the value to view objects
it will handle the screen rotations
注意:如果将来有人遇到与我相同的问题,我会发布此答案。对我来说,以下行还不够:
当我旋转屏幕时,没有调用方法`onConfigurationChanged(Configuration new config)。
解决方案:即使问题与方向有关,我也必须添加“screenSize”。因此,在 AndroidManifest.xml 文件中添加以下内容:
然后实现方法
onConfigurationChanged(Configuration newConfig)
Note: I post this answer if someone in the future face the same problem as me. For me the following line wasn't enough:
When I rotated the screen, the method `onConfigurationChanged(Configuration new config) didn't get called.
Solution: I also had to add "screenSize" even if the problem had to do with the orientation. So in the AndroidManifest.xml - file, add this:
Then implement the method
onConfigurationChanged(Configuration newConfig)
在
manifest
的活动部分中,添加:In the activity section of the
manifest
, add:人们说你应该使用
但是在 Android 中处理旋转的最好、最专业的方法是使用 Loader 类。它不是一个著名的类(我不知道为什么),但它比 AsyncTask 好得多。有关更多信息,您可以阅读 Udacity 的 Android 课程中的 Android 教程。
当然,作为另一种方式,您可以使用 onSaveInstanceState 存储值或视图,并使用 onRestoreInstanceState 读取它们。这真的取决于你。
People are saying that you should use
But the best and most professional way to handle rotation in Android is to use the Loader class. It's not a famous class(I don't know why), but it is way better than the AsyncTask. For more information, you can read the Android tutorials found in Udacity's Android courses.
Of course, as another way, you could store the values or the views with onSaveInstanceState and read them with onRestoreInstanceState. It's up to you really.
在清单中添加此行:
android:configChanges="orientation|screenSize"
Add this line in manifest :
android:configChanges="orientation|screenSize"
谷歌推出的 Android 架构最好的组件之一将满足 ViewModel 的所有要求。
它旨在以生命周期的方式存储和管理与 UI 相关的数据,并且允许数据在屏幕旋转时继续存在。
请参阅:https://developer.android.com/topic/libraries/architecture/viewmodel
One of the best components of android architecture introduced by google will fulfill all the requirements that are ViewModel.
That is designed to store and manage UI-related data in a lifecycle way plus that will allow data to survive as the screen rotates
Please refer to this: https://developer.android.com/topic/libraries/architecture/viewmodel
经过一段时间的尝试和错误,我找到了一个在大多数情况下都能满足我的需求的解决方案。这是代码:
清单配置:
MainAttivity:
和样本片段:
可以在github。
After a while of trial and error, I found a solution which fits my needs in the most situations. Here is the Code:
Manifest configuration:
MainActivity:
And sample Fragment:
Can be found on github.
使用
orientation
监听器在不同的方向上执行不同的任务。Use
orientation
listener to perform different tasks on different orientation.将以下代码放入
Android Manifest
的Activity
中。当您改变方向时,这不会重新启动您的活动。
Put this below code in your
Activity
inAndroid Manifest
.This will not restart your activity when you would change orientation.
修复屏幕方向(横向或纵向)
在
AndroidManifest.xml
android:screenOrientation="portrait"
或android:screenOrientation="landscape"
中 您的
onResume()
方法不会被调用。Fix the screen orientation (landscape or portrait) in
AndroidManifest.xml
android:screenOrientation="portrait"
orandroid:screenOrientation="landscape"
for this your
onResume()
method is not called.您可以在活动中使用 ViewModel 对象。
ViewModel 对象在配置更改期间会自动保留,以便它们保存的数据可立即可供下一个活动或片段实例使用。
阅读更多:
https://developer.android.com/topic/libraries/architecture/viewmodel
You may use the ViewModel object in your activity.
ViewModel objects are automatically retained during configuration changes so that the data they hold is immediately available to the next activity or fragment instance.
Read more:
https://developer.android.com/topic/libraries/architecture/viewmodel