Как мне выполнить другую функцию после завершения асинхронной функции в kotlin?

#kotlin #asynchronous

#kotlin #асинхронный

Вопрос:

Я создаю следующую переменную:

 phoneViewModel = ViewModelProvider(this).get(PhoneViewModel::class.java).also {it.initialRead()}
  

initialRead() вызывает другую функцию, которая извлекает данные асинхронно. Когда я использую переменную phoneViewModel в своем приложении, приложение завершает работу, поскольку функция initialRead() еще не завершена. Как я могу выполнить другую функцию, например, usePhoneViewModel() после завершения создания «асинхронного» экземпляра?

 public fun initialRead(onError: ((errorMessage: String) -> Unit)? = null) {
    if (!isDownloadError) {
        repository.initialRead(
            Action0 { isDownloadError = false},
            Action1 { error ->
                isDownloadError = true
                onError?.let {
                    val resources = getApplication<Application>().resources
                    onError.invoke(resources.getString(R.string.read_failed_detail))
                }
            }
        )
    }
}
  

и initialRead в репозитории

 fun initialRead(successHandler: Action0?, failureHandler: Action1<RuntimeException>) {
    relatedEntities.clear()

    if (initialReadDone amp;amp; entities.size > 0) {
        observableEntities.setValue(entities)
        return
    }

    var dataQuery = DataQuery().from(entitySet)
    if (orderByProperty != null) {
        dataQuery = dataQuery.orderBy(orderByProperty, SortOrder.ASCENDING)
    }

    zGW_EXT_SHIP_APP_SRV_Entities.executeQueryAsync(dataQuery,
        Action1 { queryResult ->
            val entitiesRead = convert(queryResult.entityList)
            entities.clear()
            entities.addAll(entitiesRead)
            initialReadDone = true
            observableEntities.value = entitiesRead
            successHandler?.call()
        },
        failureHandler,
        httpHeaders)
}
  

Комментарии:

1. Пожалуйста, уточните, как именно initialRead выполняется асинхронный: возвращает ли он Java Future CompletableFuture или какой-либо другой подобный тип? Это suspend функция Kotlin? Что-то еще?

2. Использовать LiveData

Ответ №1:

Учитывая эту функцию, я не думаю, что вы сможете. Добавьте onSuccess аргумент к вашему initialRead , например:

 public fun initialRead(onSuccess: (() -> Unit)? = null, onError: ((errorMessage: String) -> Unit)? = null) {
    if (!isDownloadError) {
        repository.initialRead(
            Action0 { 
                isDownloadError = false
                onSuccess?.invoke()
            },
            Action1 { error ->
                isDownloadError = true
                onError?.let {
                    val resources = getApplication<Application>().resources
                    onError.invoke(resources.getString(R.string.read_failed_detail))
                }
            }
        )
    }
}
  

а затем передайте то, что вы хотите там сделать:

 ViewModelProvider(this).get(PhoneViewModel::class.java).also {
    it.initialRead(onSuccess = { usePhoneViewModel() })
}
  

Комментарии:

1. Спасибо! Но usePhoneViewModel() никогда не вызывается. Есть идеи?

2. Может быть, вы в if (initialReadDone amp;amp; entities.size > 0) случае? Но это всего лишь предположение, и я предлагаю попробовать отладить его самостоятельно.

3. Только что отлажено, и оно переходит в executeQueryAsync и succesHandler? .вызывается вызов, но моя функция usePhoneViewModel не вызывается, хммм