为什么不能总是使用android:configChanges="keyboardHidden|orientation"?

194
我在想,为什么不在每个(几乎每个)活动中使用android:configChanges="keyboardHidden|orientation"呢?
优点: - 不用担心活动旋转 - 更快
缺点: - 如果布局依赖于屏幕大小(例如具有两列的布局),则需要更改布局。 - 没有灵活的方法在不同方向上使用不同的布局 - 在使用片段时效果不好
但如果我们不使用不同的布局,为什么不用它呢?

6
你也应该解释一下你认为keyboardHidden|orientation是做什么的。 - Blundell
这不是防止使用指定配置更改的本地处理并允许应用程序处理它吗? - Mikooos
2
这就是为什么有这个选项,如果你知道自己在做什么(不改变资源),就使用它。 - Pointer Null
为什么使用ScreenSize比使用屏幕大小更快? - Emil
4个回答

352

快速背景

在Android上发生某些关键配置更改时(一个常见的例子是方向更改),默认情况下,Android会完全重新启动正在运行的Activity以帮助它适应这些更改。

当您在AndroidManifest中定义android:configChanges =“keyboardHidden | orientation”时,您告诉Android:“当键盘被拉出或手机旋转时,请不要执行默认重置操作;我想自己处理这个问题。是的,我知道我在做什么。”

这是一件好事吗?我们很快就会看到...

没问题吧?

你开始拥有的优点之一是:

无需担心您的活动被旋转

在许多情况下,人们错误地认为当屏幕方向改变(“旋转”)引发错误时,他们只需添加android:configChanges =“keyboardHidden | orientation”即可轻松解决问题。

然而,android:configChanges =“keyboardHidden | orientation”只是一种临时措施。实际上,配置更改可以触发许多方式。例如,如果用户选择了新语言(即区域设置已更改),则您的Activity将以与方向更改相同的方式重新启动。如果您愿意,可以查看各种配置更改类型的列表

编辑:更重要的是,正如hackbod在评论中指出的那样,当您的应用程序处于后台且Android决定通过终止它来释放一些内存时,您的活动也将被重新启动。当用户回到您的应用程序时,Android会尝试以与其他配置更改相同的方式重新启动活动。如果您无法处理此问题-用户将不会满意...

换句话说,使用android:configChanges="keyboardHidden|orientation"并不是解决您的“烦恼”的方法。正确的方式是编写活动以使其能够满足Android对它们进行的任何重新启动。这是一个好的做法,将帮助您在以后的道路上,所以请习惯它。
那么什么时候应该使用它呢?正如你提到的,有一个明显的优点。通过自己处理旋转的默认配置更改来覆盖它将加快速度。然而,这种速度是以方便为代价的。
简单地说,如果您在纵向和横向都使用相同的布局,则通过执行重写操作可以很好地解决问题。视图将只需移动以填充剩余空间,而不需要完全重新加载活动。
但是,如果由于某种原因您在设备处于横向时使用了不同的布局,则Android重新加载您的Activity是好的,因为它将加载正确的布局。如果您在这样的Activity中使用覆盖,并希望在运行时进行一些神奇的重新布局... 那么好运吧-这远非简单。
总之,如果android:configChanges ="keyboardHidden | orientation"适合您,请务必测试发生更改时会发生什么,因为方向更改并不是触发完全重新启动活动的唯一方式。

51
值得强调的是,如果你不处理活动重新启动的情况,那么你面临的问题比仅仅无法处理较少常见的配置更加严重。这里使用的活动重新启动机制与 Android 在应用程序在后台被杀死时如何还原你的活动到其先前状态完全相同。因此,如果你没有正确处理,你的用户将会体验到他们从后台返回你的应用程序时,应用程序随机地无法正确恢复,具体取决于进程是否被杀死。所以一个巨大的好处是:它确保了你的应用程序正确重新启动。 - hackbod
16
从Android 3.x开始,请不要忘记添加"screenSize"——android:configChanges = ["mcc", "mnc", "locale", "touchscreen", "keyboard", "keyboardHidden", "navigation", "screenLayout", "fontScale", "uiMode", "orientation", "screenSize", "smallestScreenSize"]。 - Michael Biermann
2
我注意到当你使用configChanges属性时,你的应用程序也会忽略方向锁定功能。你如何解决这个问题?如果你知道答案,请在这里写下来:http://stackoverflow.com/questions/24000361/how-to-avoid-activity-re-creation-when-being-rotated-while-also-respecting-orie - android developer
5
当键盘被拔出时,请不要进行默认重置。我从未见过因为“键盘拔出”而导致Activity重新启动! - Muhammad Babar
2
很遗憾,这个答案没有提到官方Google文档的主要解释。主要问题在于备用资源集,在配置更改时不会自动应用,如果您想手动处理它,则需要手动处理。而且它不仅影响相关的Activity,还影响整个应用程序。 - Coryffaeus
显示剩余9条评论

3
从我的角度来看:如果横屏和竖屏模式下布局相同,您可以在应用程序中禁用其中一个。
我之所以这样说是因为作为用户,当我改变方向时,我希望应用程序能够为我提供一些好处。如果无论我如何拿着手机都没有影响,那么我就不需要选择。
例如,有一个包含ListView的应用程序,点击ListItem后会显示该项的详细信息。在横屏模式下,您可以将屏幕分成两部分,在左侧显示ListView,在右侧显示详细视图。在竖屏模式下,您将在一个屏幕上显示列表,然后在选择一个ListItem后切换到详细视图。在这种情况下,方向变化是有意义的,并且需要不同的布局。

4
是的,我们在我们应用程序的1.0版本中采用了这个方案,以配合我们的苹果发布。它仅以竖屏呈现。在我的Droid X上看起来很棒,我们完全匹配了IOS版本的弹出式键盘行为。然后,首席财务官在他的Droid上安装了该应用程序,将其旋转到一侧并打开了键盘。糟糕了。关于Android的事情是它是一个开放平台,你真的不能预测硬件配置或用户想做什么,所以你应该支持所有(多种)方向,以防万一。 - Tevo D
1
顺便提一下,由于硬件本身是以横向为正常方向而不是备选方向,这意外地覆盖了我们的仅限纵向设置。这真的破坏了我们的布局:( 这也很尴尬,因为他安装应用程序后几秒钟内就出现了一个重大缺陷。 - Tevo D
1
你为什么要让它的行为和iOS完全一样呢?:( - FunkTheMonk
7
很遗憾,我们生活在一个商人做出技术决策的世界里。即使你反对,他们有一半的时间仍认为自己是正确的。而且他们掌控着你的薪水。 - StackOverflowed
2
仅使用一个布局并不意味着在旋转屏幕时界面会保持相同。良好结构化的XML布局将导致元素自动调整以适应合理的尺寸,用户会感到满意。 - Melinda Green
显示剩余2条评论

-1

我不明白为什么...偶尔重启在我看来没问题...configChanges 对我来说处理了大多数情况...也许在某些类型的应用程序中,这可能是个问题,但这实际上取决于应用程序的类型以及当应用程序重新启动时如何恢复状态...当我的一个应用程序重新启动时,用户会被登录并且最后的活动由我的代码打开,用户只需要失去一些回到之前的步骤,但这不是什么大问题...在其他一些状态始终保持,并且某些状态始终在重新启动时恢复。当活动重新启动时,必须是应用程序没有被使用或者类似的情况...所以根本没有问题...例如,在游戏中,这可能是个问题,或者在其他某些类型的应用程序中,我不知道...

我认为,当你这样做时,应用程序在正常情况下运行得很好。而且,代码更易读,不需要大量的逻辑来保存和恢复,否则你只会制造新的错误,并且需要一直维护它...当然,如果 Android 耗尽电力并杀死您的应用程序窗口,它会丢失上下文并重新开始,但这只发生在特殊情况下,并且在较新的设备上,我相信这种情况越来越少...

别打我,但我在各种应用程序中都相当成功地使用了这个… android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" 但我知道对于某些特殊类型的应用程序来说可能不是个好方法,但大多数应用程序都可以很好地使用它。


大家好,有没有对这个话题有了解的人可以看一下我的帖子:stackoverflow.com/questions/35941585/…?我非常需要帮助。 - Luke Allison
你应该完全支持在活动中保存/恢复...对于旋转的处理并没有什么不同...你说你会失去一些步骤...如果你正确地做,你不会失去任何步骤,并且可以恢复用户离开的位置...即使设备重新启动。 - HaMMeReD
我不知道你在说什么,但是我认为当你按照这种方式进行操作时,在正常情况下应用程序可以很好地工作。而且,代码更加易读,而无需保存和恢复所需的大量逻辑,否则你只会制造新的错误并不断维护。当然,如果Android电源不足并杀死应用程序窗口,则会丢失上下文并重新开始,但这只会发生在特殊情况下,并且在更新的设备上,我相信这种情况越来越少... - Renetik
1
忽略遵守Activity契约(保存/恢复状态)是不良实践,这是非常糟糕的建议。尝试针对进程死亡进行测试,并查看您的应用程序在哪里,如果用户在手机上使用至少2-3个应用程序并在它们之间切换,则此行为完全符合“正常情况”。 - EpicPandaForce

-3

是的,我认为暂停比释放播放器更快。但仍然需要暂停。

现在已经找到了一个不会暂停歌曲的解决方案。

在清单中声明您将处理屏幕方向的配置更改,然后使用onConfigurationChanged方法加载布局文件。通过在logCat中执行此操作,我可以看到未调用onPause、onCreate和onResume,因此歌曲不会暂停。

  1. 更新清单文件以处理屏幕方向。

    android:configChanges="orientation|screenSize"
    
  2. 添加以下代码:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // TODO Auto-generated method stub      
        super.onConfigurationChanged(newConfig);        
        setContentView(R.layout.activity_main);
    }
    

你应该使用服务来播放音乐。说真的,你让人们添加仍带有“// TODO Auto-generated method stub”的代码。这是一个粗糙的解决方案。而且它也不会很好地工作,你需要重新绑定所有引用,如果你不这样做,它们最多会变得不可预测。 - HaMMeReD

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