Kotlin Android 懒惰 对象中的类初始化在杀死应用程序后仍然存在

Kotlin Android lazy Class initialisation inside Object persist after killing App

提问人:Hmerman6006 提问时间:9/27/2022 更新时间:9/27/2022 访问量:243

问:

我初始化一个在 ViewModel 中调用的 Object。此对象包含一个名为 的延迟初始化类。该类具有对令牌的类范围引用,在用户注销后,将从 SharedPreferences 中清除该令牌。
但是我在测试中注意到,如果我使用其他用户登录,新登录的用户会收到以前的用户特定数据。调试后,我了解到该类是在尝试登录的用户获得授权之前初始化的;因此,除非显式更新,否则 SharedPreferences 中设置的任何新信息都不会更新类范围信息。

奇怪的是,在注销时,所有数据库和用户特定数据都被清除、移除和删除。但是,上一个用户的令牌在新用户登录时仍然存在。这怎么可能?和 类实例将与 App 一起死亡,从 Android 设备的内存中清除。我检查了 SharedPreferences 中的持久性信息,但用户登录时不存在任何内容,Room 数据表中也没有任何数据。
当然,这并不总是发生,特别是当我从内存中清除模拟器时。它确实发生了足够多的次数,让我非常担心。

对象实例化:
DataSourceServerCallsServerCallsServerCallsDataSourceServerCallsDataSource

class StarterViewModel(
    private val starterRepository: StarterRepository,
    private val application: Application
): ViewModel() {

    init {
        DataSource.init(this.application)
    }

该对象延迟初始化一个名为 :DataSourceServerCalls

object DataSource {

    private lateinit var application: Application

    fun init(application: Application){
        this.application = application
    }

    private val _server: ServerCalls by lazy { ServerCalls(AuthApi, this.application) }

    fun fetchData(): <Response<Mountains>> = 
                           _server.fetchData(_server.token)

该类包含一个类作用域变量,该变量用行 进行初始化。在调用错误数据时,由于持久化,用户到达了错误的数据。对于给定的密钥,到达的数据是正确的。该密钥属于以前的用户。同样在这一点上,如果我输出 SharedPrefences,它也将是正确的。

当用户注销时,SharedPrefences 将使用 ;数据库 with 和 app 以 结尾。我已经多次使用不同的用户登录和注销,SharedPreferences 和数据表都很清楚。有人可以告诉我这是如何实现的吗?我错过了什么吗?
ServerCallstokenvar token = sharedPreferences.tempAuthDataSource.fetchData()_server.tokentempAuthsharedPreferences.edit().clear().apply()clearAllTablesfinishAndRemoveTask()

Android Kotlin 对象 共享首选项 android-room

评论


答:

3赞 David Wasser 9/27/2022 #1

DataSource是单例。它是在托管应用的操作系统进程启动时创建的,并且在操作系统进程被 Android 终止之前不会消失。仅调用并不一定会导致操作系统进程被终止。Android 最终会杀死没有活动组件(、 等)的操作系统进程,但它会在自己的时间这样做,不同的制造商会以不同的方式做到这一点。您无法确定 Android 何时会终止操作系统进程。finishAndRemoveTask()ServiceActivity

如果您注销应用程序并调用 ,然后再次启动应用程序以其他用户身份登录,则操作系统进程可能仍然存在,在这种情况下,实例仍将存在。finishAndRemoveTask()DataSource

评论

0赞 Hmerman6006 9/27/2022
多读一点,感谢您的回答,非常感谢。我在文档中寻找类型机制,但找不到任何明确内置于 Kotlin 语言的内容。您可能知道析构函数是否可能用于 ?还是设计在注销时清除自身的问题?design-patterns/singletondestructorsingletonsingleton
1赞 David Wasser 9/27/2022
单例没有“析构函数”。这是设计使然。单例只创建一次,也只有一次,并且永远存在。如果需要“清除”单例,请为其提供方法,并且您的应用可以在清除单例的适当时间调用该方法。