在Android(Kotlin)中处理Singleton清理的推荐方法是什么?

5

当我使用返回键关闭Android应用程序并重新进入时,发现我的两个单例类中的变量从未被重新初始化,因此出现了一些奇怪的问题(如果使用任务管理器手动杀死应用程序,则不会出现此问题)。

即使在主Activity的onBackPressed上明确调用finish并且可以看到onDestroy已经被调用,但Singletons仍然存在于内存中。

我决定在销毁我的Activity之前进行这些Singletons的手动清理,但问题是使用Kotlin,我需要将它们的所有成员变量变为可空的(?),而且记得给每一个变量赋值为null会很麻烦。所以目前我选择像这样处理Singleton的实例化,并在清理时将整个实例都设置为null:

class SingletonName {

    companion object {
        private var _instance: SingletonName ? = null
        private var instance: SingletonName ?
            get() {
                if (_instance == null) {
                    _instance = SingletonName ()
                }
                return _instance
            }
            set(value) {
                _instance = value
            }

        @JvmStatic fun get(): SingletonName {
            return instance!! //avoid having to deal with nullable value in client code
        }
    }

    //need to make sure to call this before destroying main activity
    fun cleanup() {
        instance = null
    }
}

客户端使用:

SingletonName.get().somefunc()

这似乎比应该要复杂,而且我知道这甚至不是线程安全的,但请记住,仅仅使用“object”关键字而不是“class”是行不通的,因为它会阻止任何初始化发生第二次运行应用程序(构造函数不会再次被调用,我无法强制销毁实例)。
这让我觉得值得研究Android依赖注入,但我觉得至少我的一个Singleton确实需要在很多地方访问,所以它可能也不是一个优雅的解决方案(可能需要将其重构为更小的功能)。
主要问题在于android处理销毁的方式,但我想我不能改变那个,如果应用程序活动已经被销毁,我不明白为什么它仍然保留所有非活动类的静态值。
问题是,无论使用哪种语言,你如何处理这些情况?或者你认为在这种情况下最好的做法是什么?
编辑:实际上,我刚刚用Dagger 2进行了测试,相同的问题发生了,如果我使用@Provides和@Singleton,提供的对象的成员变量的值第二次启动应用程序时不为null,所以我想这需要显式处理,除非我错过了一些更多的注释来告诉Dagger实例应该在应用程序生命周期结束时释放。

你可以创建一个名为 recreate 或其他类似的方法来重新初始化你的单例。 - Mibac
整个方法看起来很奇怪。如果你只需要在Activity可见时使用这个“singleton”,那么就在Activity内部创建一个对象即可。 - Miha_x64
@Miha_x64,问题是我需要整个应用程序的单例,是的,我猜在开始时重新创建将与在结束时进行清理相同,但问题是一样的,需要确保重置每个成员变量。 - PedroMVU
android.app.Application 将在整个应用程序的生命周期中存在。如果您想要一个生存期较短、带有 UI 并且可以在配置更改后继续存在的对象,请考虑使用 onRetainCustomNonConfigurationInstance - Miha_x64
如果该状态应该被“清理”,那么它可能与Activity或Service相关联,不应存储在全局单例中。此外,没有所谓的“关闭”Android应用程序。系统决定何时终止它。 - BladeCoder
1个回答

1

@Ascorbin 你确定你懂Kotlin吗?这是在Kotlin中创建单例的方法。你可以查看Kotlin官方文档。 - v4_adi
糟糕,抱歉!你是对的,我错过了 object 关键字。你可以移除数据库相关内容(因为它在这里无关紧要),突出显示 object 关键字并指向你发布的链接中特定的部分:https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations - fweigl
@Ascorbin 没关系。我已经删除了数据库部分。我还将链接更改为指向特定部分。您现在可以给我的答案点赞吗? - v4_adi
@v4_adi 对象的问题在于,如果你放置了一个init块,你会发现它只会在第一次执行,当你通过返回键关闭应用程序并重新启动时,不会调用任何init代码,无论成员变量中有什么,它们仍然存在,所以我仍然需要确保在某个时候重置每个成员变量。 - PedroMVU

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