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.