【问题标题】:What is the advantage of letting an activity be destroyed on rotation?让活动在轮换时被销毁有什么好处?
【发布时间】:2012-11-30 15:13:14
【问题描述】:

这两种方法我都用过:

  1. 让活动在轮换时被销毁
  2. 不要让活动在轮换时被破坏

我的方法几乎每次都是捕捉旋转事件,如果需要,调用 setContentView 并再次添加一些组件。如果没有,就让它旋转,布局会自动适应。

到目前为止,我只看到在具有非常复杂的动态结构的屏幕上销毁它的优势,并且每当我旋转而不是销毁时,在重新构建屏幕时会显示一些闪烁。

必须使用 onSaveInstance 传递状态的开销,onRestoreInstace 有时很容易出错,而且不知何故很耗时。

我错过了什么吗?

更新:

我没有在我的代码上执行任何类型的 if "Orientation.XPTO == ..."。这是两种方法中的每一种的逻辑(代码被重用):

破坏时

onCreate -> DrawUI() setContentView and add views -> fill() add content

未销毁时:

onCreate -> DrawUI() setContentView and add views -> fill() add content
onRotation -> DrawUI() setContentView and add views -> fill() add content

当在旋转后调用 setContentView 时,它会为设备方向选择正确的布局(检查这个答案由谷歌的 Reto Meier https://stackoverflow.com/a/456918/327011 )

DrawUI 和填充必须具有纵向和横向布局的逻辑,因为可以在两个方向中的每一个上创建活动。

【问题讨论】:

  • "如果重新启动活动需要您恢复大量数据、重新建立网络连接或执行其他密集操作,那么由于配置更改而完全重新启动可能会降低用户体验. 此外,您可能无法使用系统通过onSaveInstanceState() 回调为您保存的Bundle 完全恢复您的活动状态——它不是为携带大型对象(如位图)和数据而设计的其中必须先序列化然后反序列化,这会消耗大量内存并使配置更改变慢。”

标签: android rotation


【解决方案1】:

我错过了什么吗?

是的。您假设您的替代方案不太容易出错。

通过不经历销毁和重新创建周期,您必须确保为每个可能的配置更改处理更改每个资源。

不要让活动在旋转时被破坏

除非您使用android:screenOrientation 强制您的活动进入单一方向(例如,landscape),否则您不能只处理与旋转相关的配置更改。您需要处理所有配置更改。否则,一旦用户将他们的设备放入 Dock、将其从 Dock 中移除、从“设置”更改语言、附加或分离键盘、更改全局字体缩放等,您的应用就会中断。

反过来,这意味着在每次配置更改时,您需要:

  • 更新您的 UI 以获取潜在的新字符串资源
  • 调整或重新加载您的布局(通过“调整”,包括更改任何可绘制对象、动画、菜单等)
  • 与您的资源相关的任何其他内容(例如,PreferenceFragment 中的数组列表)

问题是你会忘记一些东西。例如,您将错过更改与操作栏项目关联的字符串,因此现在您的大部分 UI 都是西班牙语,而操作栏项目是英语。你会忘记的那些事情会变得不那么明显(你多久测试一次你的西班牙语翻译?)。

【讨论】:

  • 除了更“容易出错”之外,还有什么性能问题吗?
  • @NeTeInStEiN:通常不会。
【解决方案2】:

您的活动被销毁,让您有机会重新配置自己以适应新的方向。

来自 developer.android.com:

当屏幕改变方向时,系统会销毁并重新创建 前台活动,因为屏幕配置已更改 并且您的活动可能需要加载替代资源(例如 布局)。

例如,在横向模式下,您可能需要完全不同的布局,或者可能希望加载不会显示为拉伸的图形。这样做的最佳方式是允许再次创建活动,这将允许链接到布局文件更改为对方向更友好的布局。

请参阅http://developer.android.com/training/basics/activity-lifecycle/recreating.html 了解更多信息以及如何处理方向变化

如果你想禁用你可以添加的游戏

android:configChanges="orientation"

到 AndroidManifest.xml 中的 Activity 元素。这样你的 Activity 就不会被重新加载。

onSaveInstance 和onRestoreInstace 只能用于传递会话信息,例如TextField 中的当前文本,并且没有可以在onCreate 之后再次加载的通用内容。

【讨论】:

  • 是的。但是,如果您使用 android:configChanges="orientation" 您也可以 setContentView 并且该特定方向的布局将被正确加载。所以……还是没有优势?
  • 如果你有一个活动可能不是一个优势,但对于更大规模的活动,你必须确保加载了正确的资源,你可能会编写大量代码来执行此操作。活动重新创建将消除这种需要,您不必担心处理刷新。
  • 如果你从一开始就处理它,那不是真的。检查更新的问题。
【解决方案3】:

如果您在重新启动 Activity 时需要恢复大量数据、重新建立网络连接或执行其他密集操作,那么使用 onSaveInstanceState() 可能会导致您注意到的症状:

  1. 糟糕的用户体验(即“显示一些闪烁”)
  2. 需要消耗大量内存

onSaveInstanceState() 回调不是为携带大型对象而设计的。

在运行时配置更改期间保留对象:

重写onRetainNonConfigurationInstance() 方法以返回您想要保留的对象。 当您的活动再次创建时,调用getLastNonConfigurationInstance() 来恢复您的对象。

但是:

虽然您可以返回任何对象,但绝不应传递与 Activity 相关联的对象,例如 Drawable、Adapter、View 或与 Context 关联的任何其他对象.如果这样做,它将泄漏原始活动实例的所有视图和资源。 (资源泄漏意味着您的应用程序会保留它们,并且无法对它们进行垃圾回收,因此可能会丢失大量内存。)

Source


除非你能够顺利通过Object(s) 我个人认为自己处理配置更改更有优势,意思是不要破坏。

如果您的目标 API 为 13 或更高:您必须在您的 configChanges 中包含 screenSize。从 API 13 开始,屏幕尺寸也会随着方向的变化而变化,您需要考虑到这一点。在 13 之前,您的 Activity 将自行处理。

android:configChanges="orientation|screenSize"

【讨论】:

    【解决方案4】:

    当您为(横向/纵向)使用不同的布局时,有时它会很有用。并使用不同类型的视图,例如纵向的ListView 和横向的GridView。

    【讨论】:

    • 是的。但是,如果您使用 android:configChanges="orientation" 您也可以 setContentView 并且该特定方向的布局将被正确加载。所以……还是没有优势?
    • 但是正如我所说,如果您使用不同的组件,那么您必须首先检查来源,然后像 ListView 和 GridView 一样填充适当的视图。
    • 没有。代码与销毁活动相同。检查更新的问题。
    【解决方案5】:

    我猜你没有考虑创建 android 布局的标准方法。如果我错了,请纠正我。您是否分别使用两个带有 -port,-land 的 res 文件夹来告诉 android 系统在运行时选择根据方向加载不同的资产和布局。

    这个example 可以为您提供管理不同方向布局的线索。

    这里是安卓stanard document。请检查“土地”和“港口”。

    希望这会对你有所帮助。

    【讨论】:

    • 为了处理非常动态的布局更改,我通常使用片段推送/弹出布局。我只需要保存 ui 的状态(如果有的话,用户输入)并在使用所需的片段更改方向后填充它,而不是让它破坏。通过这种方式,它变得非常易于管理。
    • "你是不是分别使用两个带有-port,-land的res文件夹来告诉android系统在运行时选择根据方向加载不同的资产和布局。" - 是的
    • 你看过我建议的例子了吗?
    • 对于任何系统,您都有两个选项可用于任何应用程序。 “一直以来,通过每次销毁/创建或保留在内存中并在需要时使用(如果真的非常复杂),都会给处理器带来开销。”为您的应用明智地选择。第一个会耗尽电池电量,第二个会消耗内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多