Блокировка класса приложения с помощью runBlocking kotlin - PullRequest
0 голосов
/ 17 июня 2019

У меня путаница по поводу того, как работают Диспетчеры в Котлине

Задача В моем классе Application я намереваюсь получить доступ к своей базе данных через Room, убрать пользователя, достать его JWT accessToken и установить его в другом объекте, который использует мой перехватчик запросов на модификацию.

Однако я хочу, чтобы весь этот код блокировался, чтобы, когда класс Application завершил свою работу, пользователь был извлечен и установлен в Inteceptor.

Задача Мой класс приложения работает до завершения, прежде чем пользователь будет выбран из базы данных.

Сессионный класс - это тот, который обращается к Комнате

Вот так выглядит мой сессионный класс

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.
}

Это мой класс приложения

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, который создает сессию

val platformModule = module {

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


}

В моем Logcat сначала выводится «Запуск приложения», а затем «Пользователь установлен»

Не должно ли быть наоборот? , Это приводит к тому, что мое приложение запускается без участия пользователя Session и жалоб MainActivity.

1 Ответ

2 голосов
/ 17 июня 2019

by inject() использует ленивую инициализацию kotlin. Блок init будет запущен только при запросе session.loggedUser.

В вашем случае, когда вы вызываете session.loggedUser в MainActivity, блок init сработает и заблокирует вызывающий поток.

То, что вы можете сделать, это.

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")


    }

...