简体   繁体   中英

Make wait another method until coroutine finishes [Android Kotlin]

I want to make wait method getCurrentUser or notify the method until the coroutine is finishes. Because variable conversationKit which is initialised in coroutine is used in method. Coroutine is launched inside the method integrateConversationKit .Both methods are invoking in onCreate in MainActivity . But I am getting the error lateinit property conversationKit has not been initialized.

    class ConversationKitService(private val context: Context) {
       private val scope = CoroutineScope(Dispatchers.Main)
       lateinit var conversationKit: ConversationKit
    
        fun integrateConversationKit() {
        
        
                val job = scope.launch {
                    val result = conversationKitFactory.create(
                        settings = settings
                    )
        
                    when (result) {
        
                        is ConversationKitResult.Success -> conversationKit = result.value
                        is ConversationKitResult.Failure -> println(result.message)
                    }
                }
        
        
            }
        
        
            fun getCurrentUser(): User? {
        
                return conversationKit.getCurrentUser()
            }
    }

You could use a Flow s for updating the conversationKit reactively, then return it's first non-null value

 class ConversationKitService(private val context: Context) {
       private val scope = CoroutineScope(Dispatchers.Main)
       private val conversationKit = MutableStateFlow<ConversationKit?>(null)
    
       fun integrateConversationKit() {
                val job = scope.launch {
                val result = conversationKitFactory.create(
                        settings = settings
                    )
        
                    when (result) {
        
                        is ConversationKitResult.Success -> conversationKit.value = result.value
                        is ConversationKitResult.Failure -> println(result.message)
                    }
                }
        
        
            }
        
        
            suspend fun getCurrentUser() = conversationKit.first{ it != null }.getCurrentUser()
            
    }

I would just make the getCurrentUser a suspend call that fetches the ConversationKit from an internal suspend call that caches the result

   class ConversationKitService(private val context: Context) {
       @Volatile
       private var conversationKit: ConversationKit? = null

       ...

       suspend fun getCurrentUser() = getConversationKit()?.getCurrentUser() 

       private suspend getConversationKit(): ConversationKit? {
           if (conversationKit != null) return conversationKit
           val result = conversationKitFactory.create(settings = settings)
           conversationKit = when (result) {
               is ConversationKitResult.Success -> result.value
               is ConversationKitResult.Failure -> null           
           } 
           return conversationKit
       }          
   }

A null value then implies an error to retrieve the value. You could also wrap that in some kind of Result so that you return a success / failure rather than a nullable value.

If what you are really trying to do, though, is to make getCurrentUser a non-suspending blocking call that doesn't require a coroutine to use it then you could use runBlocking :

   class ConversationKitService(private val context: Context) {
       @Volatile
       private var conversationKit: ConversationKit? = null

       ...

       fun getCurrentUser() = runBlocking { 
           getConversationKit()?.getCurrentUser()
       }

       private suspend getConversationKit(): ConversationKit? {
           if (conversationKit != null) return conversationKit
           val result = conversationKitFactory.create(settings = settings)
           conversationKit = when (result) {
               is ConversationKitResult.Success -> result.value
               is ConversationKitResult.Failure -> null           
           } 
           return conversationKit
       }          
   }

I wouldn't really recommend this approach, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM