Home > Blockchain >  Kotlin Android lazy Class initialisation inside Object persist after killing App
Kotlin Android lazy Class initialisation inside Object persist after killing App

Time:09-27

I initialise an Object called DataSource inside a ViewModel. This object contained a lazily initialised class called ServerCalls. The ServerCalls class had a class scope reference to a token which after a user logged out was cleared from SharedPreferences.
But I noticed in testing that if I logged in with a different user the newly logged in user received the previous user specific data. After debugging I came to the understanding that the ServerCalls class was initialised before the user trying to log in was authorised; therefore any new information set in SharedPreferences would not update the class scope information unless done so explicitly.

The strange thing though is that on logout all databases and user specific data was cleared, removed and deleted. BUT the token of the previous user persisted on a new user logging in. How can that be? The DataSource and ServerCalls class instance would die with the App, cleared from memory of the Android device. I checked the SharedPreferences for persistent information, but nothing exists when a user logs in nor are there any data in the Room data tables.
Of course this did not occur always, especially if I cleared the emulator from memory. It did occur enough times for me to get very worried.

DataSource object instantiation:

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

    init {
        DataSource.init(this.application)
    }

The DataSource object lazily initialises a class called ServerCalls :

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)

The ServerCalls class contains a class scope variable token that gets initialised with line var token = sharedPreferences.tempAuth. On calling DataSource.fetchData() the wrong data arrives for the user, due to persisted _server.token. The arriving data is correct for the given key. The key belongs to the previous user. Also at this point if I output the SharedPrefences tempAuth it will also be correct.

When a user logs out the SharedPrefences is cleared with sharedPreferences.edit().clear().apply(); Database with clearAllTables and app ends with finishAndRemoveTask(). I have logged in and out with a different user numerous times and the SharedPreferences is clear as well as the data tables. Can someone maybe give me insight on how this is possible? Am I missing something?

CodePudding user response:

DataSource is a singleton. It is created when the OS process hosting the app starts and doesn't go away until the OS process is killed by Android. Just calling finishAndRemoveTask() doesn't necessarily cause the OS process to be killed. Android will kill off OS processes that have no active components (Service, Activity, etc.) eventually, but it does this on its own time and different manufacturers do this in different ways. You cannot be sure when Android will kill off the OS process.

If you log out of your app and call finishAndRemoveTask(), then you start your app again to log in as another user, the OS process may still be around, in which case the DataSource instance will still exist.

  • Related