1

I have a confusion about how Dispatchers work in Kotlin

Task In my Application class I intend to access my database via Room, take out the user , take out his JWT accessToken and set it in another object that my retrofit Request inteceptor uses.

However I want all this code to be blocking , so that when the Application class has ran to its completion , the user has been extracted and set in the Inteceptor.

Problem My application class runs to completion BEFORE the user has been picked from the database.

Session class is the one which accesses Room

This is how my session class looks

class Session(private val userRepository: UserRepository, private var requestHeaders: RequestHeaders) { var authenticationState: AuthenticationState = AuthenticationState.UNAUTHENTICATED var loggedUser: User? by Delegates.observable<User?>(null) { _, _, user -> if (user != null) { user.run { loggedRoles = roleCsv.split(",") loggedRoles?.run { if (this[0] == "Employer") { employer = toEmployer() } else if (this[0] == "Employee") { employee = toEmployee() } } authenticationState = AuthenticationState.AUTHENTICATED requestHeaders.accessToken = accessToken } } else { loggedRoles = null employer = null employee = null authenticationState = AuthenticationState.UNAUTHENTICATED requestHeaders.accessToken = null } } var loggedRoles: List<String>? = null var employee: Employee? = null var employer: Employer? = null init { runBlocking(Dispatchers.IO) { loggedUser = userRepository.loggedInUser() Log.d("Session","User has been set") } } // var currentCity // var currentLanguage } enum class AuthenticationState { AUTHENTICATED, // Initial state, the user needs to secretQuestion UNAUTHENTICATED, // The user has authenticated successfully LOGGED_OUT, // The user has logged out. } 

This is my Application class

class MohreApplication : Application() { private val session:Session by inject() private val mohreDatabase:MohreDatabase by inject() // this is integral. Never remove this from here. This seeds the data on database creation override fun onCreate() { super.onCreate() startKoin { androidLogger() androidContext(this@MohreApplication) modules(listOf( platformModule, networkModule, .... )) } Log.d("Session","Launching application") } 

My Koin module which creates the session

val platformModule = module { // single { Navigator(androidApplication()) } single { Session(get(),get()) } single { CoroutineScope(Dispatchers.IO + Job()) } } 

In my Logcat first "Launching Application" prints out and THEN "User has been set"

Shouldn't it be reverse? . This is causing my application to launch without the Session having the user and my MainActivity complains.

3
  • What are you trying to accomplish? What is the purpose of a "phantom delay"? Commented Jun 17, 2019 at 18:45
  • Pawel I am updated my real problem Commented Jun 17, 2019 at 18:58
  • @MuhammadAhmedAbuTalib hey! this is too much implementation detail. try to boil it down to the most important part. try to create a minimal example of what you want to achieve. Commented Jun 17, 2019 at 19:09

1 Answer 1

2

by inject() is using kotlin lazy initialization. Only when session.loggedUser is queried will the init block be fired.

In your case, when you call session.loggedUser in the MainActivity, the init block will fire and block the calling thread.

What you can do is.

import org.koin.android.ext.android.get class MohreApplication : Application() { private lateinit var session: Session private lateinit var mohreDatabase: MohreDatabase // this is integral. Never remove this from here. This seeds the data on database creation override fun onCreate() { super.onCreate() startKoin { androidLogger() androidContext(this@MohreApplication) modules(listOf( platformModule, networkModule, .... )) } session = get() mohreDatabase = get() Log.d("Session","Launching application") } 
Sign up to request clarification or add additional context in comments.

2 Comments

That makes a lot of sense. Ill try to create my Session class away from Koin and report back the results
@MuhammadAhmedAbuTalib I've updated my answer to fix your problem.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.