Android中的静态单例生命周期

Posted

技术标签:

【中文标题】Android中的静态单例生命周期【英文标题】:Static singleton lifetime in Android 【发布时间】:2012-12-03 04:37:36 【问题描述】:

我有一些不清楚的情况:

在最后一个引用持有 Activity 被销毁后,静态单例是否会被垃圾回收?因为 Application 中不再有对单例实例的引用。那么我可以依赖单身人士吗?

官方android doc:

通常不需要子类化应用程序。在大多数情况下, 静态单例可以以更模块化的方式提供相同的功能 方式。

通过一些帖子:

https://web.archive.org/web/20160729201921/http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

在开发应用程序时,我发现 有时一些绑定到活动的静态变量发生在 即使它们之前已被初始化,也不会被初始化!一世 认为当一个静态变量被初始化时,它保持不变 应用程序的整个生命周期,但似乎并非如此。

换句话说,如果没有任何东西持有对我的静态单例类的引用,那么如何防止它被垃圾收集和销毁?

【问题讨论】:

@Arvis 你可以依赖的是全局静态变量。在您的应用程序进程被系统杀死之前,这些不会被垃圾收集。 【参考方案1】:

不,因为如果它是单例,它会在其类中存储为static 字段,并且通常单例不会被客户端销毁,即您不会放置一个静态方法deleteInstance(),它将引用设置为@ 987654325@ 这样如果没有其他人使用它,它就有资格进行垃圾收集。对于静态字段,当加载该类的类加载器被丢弃时,就会发生垃圾回收。

由于这个原因,static这个关键字本身可能会导致内存泄漏,如果它引用了Activity对象,所以在使用的时候要非常小心。

【讨论】:

这在 android 中是不正确的。当应用程序不在前台时,dalvik VM 可能会破坏类以及任何静态变量,并且设备需要释放内存。 你在哪里读到的?当活动不在前台时,Android 可以销毁活动,但不会违反 Java 规则。事实上,如果您的活动在任何地方被引用,它们就不能被垃圾收集,并且您有泄漏。 Romain Guy 有一篇关于此的帖子。不要期望 Android 是一个 疯狂 系统,只会在内存不足时破坏周围的对象。 我经历过。在硬件较弱的设备上,每当您的应用程序进入后台时,您的应用程序对象以及您的活动通常都会被销毁,然后在后台重新创建。在这种情况下,如果您不在static 块中初始化它们,即使您的静态变量也会变为空。这是关于这个***.com/questions/9541688/…的SO线程 也许可以,但关键是一旦进程被杀死,并不是静态字段设置为null。简单地说,应用程序再次被引导,所有类对象也是如此,它们的所有字段也是如此。它不会破坏标准 Java,因为应用程序是从头开始的 @AdamL.Mónos Here is a demo project。第一个活动包含一个静态字段,每个 onResume() 占用更多内存。注意onResume()必须在onPause()之后调用,这意味着Activity离开了前台,可以被销毁。静态字段仍然永远不会取消,它最终会触发 OutOfMemoryError【参考方案2】:

是的。每次您离开应用程序时(例如,您的应用程序打开相机应用程序拍照,或打开浏览器打开链接,或者用户只是按下后退按钮),您的 Application 对象可能会当您导航回您的应用程序时被销毁并重新创建。

您应该在自定义 Application 类中的 static 块中初始化任何静态变量(如果有的话),或者在您的 Activities 中初始化,以确保它们不会为空。

请注意,在硬件较弱、内存较低的设备上更有可能遇到此问题,但您应该期望它可能发生在任何设备上。

底线是,在 android 中,不要期望您的静态变量会随时留在内存中。始终检查它们是否存在,并在必要时在正确的位置重新初始化它们。

编辑:

我知道已经很久了,我完全忘记了这个线程,无论如何,这里是官方Android生命周期文档的来源:

http://developer.android.com/training/basics/activity-lifecycle/recreating.html

【讨论】:

如果应用程序进程被杀死 - 没关系,没有问题,下次我运行一个新进程时必须创建一个新进程,所有进程都将重新初始化。但我谈到了 Activity 何时被杀死或销毁。 @Arvis 不用担心单身人士。 Here is a test 表明它们永远不会被丢弃。顺便说一句,为什么你需要共享一个原始套接字?如果您的问题不是理论上的,而是特定于应用程序的,请添加更多信息,我们会回答。您引用的帖子似乎完全错误:除非可以复制或链接文档,否则我们不能假设在应用程序进程处于活动状态时在运行时卸载静态字段(即类实例) @Arvis 如果您查看该问题的答案,他们都同意在进程处于活动状态时不会卸载类。所以,再一次,你不应该担心你的静态字段突然变成空 @AdamL.Mónos 有趣的是,这个答案只有两种不同的意见:“如果 Activity 被卸载,那么你的单身人士也是如此”和“不要担心单身人士......他们是永远不会扔掉” :) 无论如何,感谢您的帮助。 @AdamL.Mónos:“类将被卸载并在您稍后返回时重新创建”--> 请提供文档【参考方案3】:

您无法控制 Java 对象何时被垃圾回收。当一个对象不再有(非循环)引用时,它就有资格进行垃圾回收。此外,在 Android 中,您无法控制 Activity 何时从内存中删除。

单例应该代表永远存在的东西。

您不能强制对任何对象进行垃圾回收;您可以请求垃圾收集器使用System.gc() 运行,但这只是一个请求。

1234563 .显然,下次有人要求实例时,就需要重新创建它。当然,此时它并不是真正的单例。

【讨论】:

确切地说:单例应该代表始终存在的东西。但这并不总是正确的。因此我不能依赖单身人士! @Arvis Application 类将是最后一个被销毁的类,它所持有的单例将比使用它们的任何其他活动寿命更长。 @Singularity 在自定义 Application 类的情况下,一切都很清楚,但我试图了解如何使用单例而不是 Application 类(旁边也是单例),因为 android 鼓励我们:“那里通常不需要继承 Application。在大多数情况下,静态单例可以以更模块化的方式提供相同的功能。”【参考方案4】:

即使活动被销毁,所有单例对象也将保留。

【讨论】:

以上是关于Android中的静态单例生命周期的主要内容,如果未能解决你的问题,请参考以下文章

[转]Android静态变量的生命周期

C++17 和静态临时生命周期的引用扩展

公共静态变量和Android活动生命周期管理

视觉知识单例模式

使用单例模式造成的内存泄漏

安卓面试中高级面试