【问题标题】:Orientation Change results in Activity instance count increase方向更改导致 Activity 实例计数增加
【发布时间】:2012-10-30 05:49:35
【问题描述】:

我有一个TestActivity。此活动将在按下Button 时从主要活动开始。 这就是我的测试活动在清单文件中的声明方式。

  <activity
        android:name="com.example.MyTestActivity"
        android:configChanges="keyboard|keyboardHidden"
        android:label="MYTESTACtivity"
        android:theme="@style/someTheme"
        android:windowSoftInputMode="stateHidden|adjustPan" >
    </activity>

现在的问题是,一旦显示TestActivity 屏幕,如果我进行方向更改,那么TestActivity 的实例计数将增加 1。如果我再次将其更改为纵向模式,它会增加还有1个。这就是在方向更改期间实例计数不断增加的方式。

无论方向发生什么变化,请告知如何一次只制作一个活动实例。 我也试过添加android:launchMode="SingleTop" 仍然存在同样的问题。 仅供参考,这就是我能够在严格模式下找到实例计数的方式。

01-02 01:39:48.855: E/StrictMode(21992): android.os.StrictMode$InstanceCountViolation: class com.example.MyTestActivity; instances=20; limit=1

【问题讨论】:

  • 尝试使用 android:launchMode="singleInstance"
  • android:singleInstance 不推荐使用,因此也不能使用。
  • 你有上下文泄漏吗?您可能会在应用程序的其他地方保留对活动中某些内容的引用,这会阻止活动的先前实例被垃圾收集。
  • 我不这么认为,我在 layout 和 layout-land-xhdpi 文件夹中有 2 个不同的布局,我也没有使用 android:configChanges 声明我的活动。因此 onCreate() 会随着方向的变化而一次又一次地被调用,并且我的活动实例数正在增加。我也不能声明 android:configChanges 因为那样我也不能使用 onSaveInstanceState 和 onRestoreInstanceState。
  • 预期会调用 onCreate()。每次更改方向时,您的活动都会被销毁,然后重新创建,这会导致调用 onCreate()。但是,似乎现有实例没有被破坏,而我所知道的唯一原因就是泄漏。是否可以发布您的活动代码?

标签: android count orientation instance


【解决方案1】:

onCreate() 调用是预期的。每次更改方向时,您的活动都会被销毁,然后重新创建,这会导致调用 onCreate()。但是,似乎现有实例没有被破坏,而我所知道的唯一原因就是泄漏。一个常见的原因是当 Activity 被销毁时没有取消绑定位图。

【讨论】:

  • 还要补充西蒙的答案,我认为严格模​​式代码存在问题。我在我的 Activity 的 onDestroy() 中调用了 System.gc() 并重新运行相同的用例,现在它达到的最大计数是 6 左右,如果我给一点时间,在严格模式下显示的活动计数日志甚至下降到 2,我知道我们不需要从我们的活动中调用 System.gc(),但只是想看看这是否真的是我的活动中的内存泄漏。所以它就像严格模式显示对一个较弱的引用活动,但是一旦垃圾收集器工作完成,严格模式就会正确显示实际活动计数。
【解决方案2】:

我决定将我的评论移至答案并扩展它,希望其他发现此帖子的新人不会在没有进一步考虑的情况下接受此解决方案:

android:configChanges:orientation|屏幕尺寸

Android 旨在销毁和重新创建您的配置更改活动,这是有充分理由的。通过将其添加到清单中,您正在执行的操作是在说“我了解我在做什么。我不希望 Android 按照设计的方式运行,我将处理所有后果。

在某些情况下,这是正确的解决方案,但在大多数情况下,这是错误的解决方案,远非“我的问题已解决”,事实上,您的问题可能才刚刚开始,因为您必须编写更多代码才能完成Android会自动完成。更多代码 = 更多错误 = 更低的可维护性。

OP 没有提供足够的细节来提供准确的答案,但一般正确的答案是了解 Activity 生命周期(即 Android 的设计工作方式)并考虑它如何应用于您的应用以及如何处理各种回调。特别是,了解 onCreate()、onStart() 和 onResume() 以及 onPause() 和 onStop() 之间的区别是关键。例如,在 onCreate() 中放置大量代码是初学者常见的错误。我见过几乎所有重要代码都在 onCreate() 中完成的应用程序,但它并不漂亮。开发人员第一次按下主页按钮,然后返回到他们的应用程序并想知道为什么它不能正常工作。

http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Yddl 在这里给出了一个很好的解释:

Why not use always android:configChanges="keyboardHidden|orientation"?

如果您想投票,请投票给他,因为我所做的只是参考他的回复。

【讨论】:

    【解决方案3】:

    默认情况下,当屏幕方向在运行时改变(用户旋转了设备)时,Activity 会关闭并重新启动。为了防止这种情况,请在您的清单中添加以下内容。

    android:configChanges="keyboardHidden|orientation"

    所以您的清单将如下所示。

    <activity
        android:name="com.example.MyTestActivity"
        android:configChanges="keyboard|keyboardHidden"
        android:label="MYTESTACtivity"
        android:theme="@style/someTheme"
        android:windowSoftInputMode="stateHidden|adjustPan" 
        android:configChanges="keyboardHidden|orientation">
    </activity>
    

    更多信息请查看this

    【讨论】:

    • 确保您阅读了该链接。许多人认为 android:configChanges="keyboardHidden|orientation" 是一种解决方案,但不了解它的作用。学习 Activity 生命周期,developer.android.com/guide/components/activities.html,然后思考您的应用需要如何处理它是正确的方法。
    • 我有一个单独的布局更改需要在横向模式下显示,因此我不能将此 android:configChanges:orientation|screensize 关键字放在我的应用程序中。谢谢
    【解决方案4】:

    尝试添加这个:

    <activity
        android:name="com.example.MyTestActivity"
        android:configChanges="keyboard|keyboardHidden|orientation"
       ...../>
    

    您的活动不会在迎新活动期间重新开始。

    【讨论】:

    • 当您发现 20 个实例仍在运行时,这正是您不想做的事情。存在明显的泄漏,应予以处理。不处理它将确保您的应用程序在当前未使用时使用的资源超出了必要的资源,这对最终用户来说是非常糟糕的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    相关资源
    最近更新 更多