【问题标题】:android memory management in activity lifecycle活动生命周期中的android内存管理
【发布时间】:2011-06-27 11:09:46
【问题描述】:

我的问题有点复杂。

我想了解应用在 Activity 启动和暂停时如何处理资源(尤其是背景图片、按钮等)。

例如,我启动 Activity A,它在屏幕上显示所有图像,吃掉它的内存,然后启动另一个 Activity B 并暂停 A。所有图像、资源等会发生什么?他们什么时候被释放?我怎样才能控制它们?我不应该将Activity A保留在内存中并将其从Activity堆栈中移除吗?

如果您需要对我的问题进行任何澄清,请写信给我!

提前致谢! 达尼尔

【问题讨论】:

标签: android memory android-activity


【解决方案1】:

在回答你的问题之前,我有一些事实要讨论。

    1234563 /p>
  1. Android 正在维护 Drawable 缓存,用于 Activity 设计和显示在屏幕上。因此,如果您在 Activity onCreate() 上禁用可绘制缓存。

所以最好的做法是像这样在onCreate 上禁用可绘制缓存:

 LinearLayout v = (LinearLayout) findViewById(R.id.mainLayout);
        v.setDrawingCacheEnabled(false);

并在onPause() 上致电finish();

【讨论】:

    【解决方案2】:

    好的,所以我们有以下情况:

    A > onCreate
    A > onStart
    A > onResume
    A > Use up a load of memory (A could even use up too much and crash)
    A > Launch activity B
    B > onCreate
    A > onPause
    B > onStart
    A > onStop
    B > onResume
    B > Use up a load of memory 
    

    如果 B 用完足够的内存,那么 Android 系统将杀死活动 A(您会注意到 A 的 onPause 和 onStop 方法已经被调用,因此它已经有机会保存它的状态)

    如果您随后按下后退按钮,Android 系统将再次启动活动 A(如果它很聪明,它应该记住它的最后状态),因此用户看起来好像什么都没发生过。

    所以要更清楚一点:如果你启动 B 然后完成 A,B 基本上只会替换活动堆栈中的 A,在活动 B 中按下后退按钮只会退出你的应用程序,不会 回到活动 A。

    另一方面,如果您在未完成 A 的情况下启动 B,则在 B 中按下后退按钮带您回到 A。当活动 A 在后台时,它可能会被杀死以回收内存,但当用户浏览活动堆栈时,Android 会根据需要重新创建它。

    此外,如果您有多个对象(例如位图/可绘制对象)的内存缓存,则通过 SoftReferences 支持您的集合,以便 GC 可以在内存不足时清除它们。

    【讨论】:

      【解决方案3】:

      您应该设计您的应用程序,使其内存使用率较低,但您可以指望框架在内存管理方面做得最好。因此,只有在您的应用明显占用过多内存的情况下,才不要过于努力地删除未使用的内容。

      当可用内存下降时,框架将停止并删除与当前任务无关的活动和服务。如果您的应用程序占用更多内存,框架将停止您在后台的活动。然后是与您的应用关联的服务,最后完成的服务将是当前活动。

      当框架停止一个活动时,它会记录活动堆栈、用于启动活动的意图和 onSaveInstanceState() 返回的包,因此它可以重新创建活动的最后一个已知状态。此外,框架可以在不使用时卸载未使用的资源(可绘制对象等),并在需要时重新加载它们。

      【讨论】:

        【解决方案4】:

        活动在完成之前不会释放资源。但在大多数情况下,这对您来说一定不是问题。在我看来,在大多数情况下,您不应该添加自己的资源管理并使代码变得复杂。

        但是如果你真的认为你的应用可能内存不足,你应该用MAT之类的东西来检查它。内存问题可能是由内存泄漏引起的,而不是内存使用量过大。

        最终,当您完全确定必须采取措施减少内存使用时,您可以进行一些内存优化。例如,您可以将消耗内存的对象(例如大图像)保存到onStop() 的本地存储中,并在onStart() 中加载它们。我认为为此目的使用onPause()/onResume() 是个坏主意,因为 Activity 是部分甚至完全可见的。

        理论上,您甚至可以在onStop() 中销毁所有小部件并在onStart() 中恢复它们,但这会使您的应用程序太慢。当然,在这种情况下,状态保存必须由您自己实现。

        完成活动似乎是个好主意,但我认为不是。首先,它会让你的工作变慢。其次,您必须自己管理活动堆栈和活动状态。 例如,Activity A 启动 Activity B。因此,Activity B 必须知道当用户按下返回按钮时该做什么。当用户按下返回按钮时,您应该启动 Activity A 并恢复其状态。但是如果用户终止这个应用程序怎么办。在这种情况下,您必须使用其默认状态初始化 Activity A。所以,你必须实现很多额外的逻辑。

        最后,我将再次重复主要思想:如果您不确定是否必须优化内存使用,请不要优化!

        【讨论】:

        • 框架释放当前活动无法访问的内存。这意味着所有对象、图像等。即使您引用了图像但当前未显示(假设您从资源加载它),图像也会被卸载。只需正确执行 onCreate()、onResume()、onPause()、onSaveInstanceState() 和 onRestoreInstanceState(),您就可以设置好。对 Android 框架的东西进行自己的内存管理会减慢速度,并且更容易出错。
        • 我刚刚浏览了ImageView 源代码,我真的不认为它会在活动停止时卸载它的可绘制对象。我也不认为TextViews 会卸载它的文本。实现您提到的方法意味着进行自己的内存管理。使用模型还是使用 GUI 的一部分并不重要。
        【解决方案5】:

        在编写 Java 代码时,您几乎无法控制内存。对于大多数情况来说,这是一件好事。其实大部分应用程序都不需要担心内存问题。

        为了回答您的问题,活动 A 的所有对象在暂停时仍将在内存中。 VM 将在需要资源时启动 GC。

        【讨论】:

        • 我知道我在Java中几乎没有控制权,虽然我可以控制它(例如,我每次恢复活动时加载位图并在每次暂停时卸载它,否则我会内存不足例外)。我的问题是关于资源,例如在 xml 中定义的背景,如果它们在活动暂停时被卸载。如果我想节省内存,我应该从活动堆栈中删除活动。内存的内部 (OS) 优化是什么。
        • 恕我直言,我怀疑该平台是否会为您进行此类优化。活动所需的所有资源在加载后都将在内存中(当然,直到它们被 GC)。
        猜你喜欢
        • 2012-12-17
        • 1970-01-01
        • 2013-01-13
        • 2011-12-18
        • 1970-01-01
        • 1970-01-01
        • 2014-09-26
        • 2012-08-24
        • 2013-08-08
        相关资源
        最近更新 更多