Как стать автором
Поиск
Написать публикацию
Обновить

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

Мне кажется пример не самый удачный. Блюрить картинку вы ещё должны до того как она попадёт в адаптер в главный поток. И обычно это типичный подход, так делают(трансформации, блюры и тд) наверное почти все загрузчики картинок.

Да и вообще, чем вам не нравится «дедовский» способ?

В принципе, подход имеет право на жизнь, но я бы изменил несколько моментов:


  1. Зачем backgroundTask знать о scope? Это похоже на нарушение инкапсуляции.
  2. В блоке result было бы неплохо сразу иметь доступ ко View
  3. isActive не будет работать, как задумывается. Вы делаете await уже после проверки isActive, соответственно, если корутина успела хотя бы запустится, проверка будет бесполезна.
  4. Зачем запускать job в главном потоке?

Я бы сделал как-то так:


inline fun <T, reified R : View> R.doAsync(
    crossinline backgroundTask: suspend () -> T?,
    crossinline onResult: R.(T?) -> Unit
) {
    val job = CoroutineScope(Dispatchers.Default)
    val attachListener = object : View.OnAttachStateChangeListener {
        override fun onViewAttachedToWindow(p0: View?) {}
        override fun onViewDetachedFromWindow(p0: View?) {
            job.cancel()
        }
    }
    addOnAttachStateChangeListener(attachListener)
    job.launch {
        val data = try {
            backgroundTask()
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
        if (isActive) {
            try {
                withContext(Dispatchers.Main) { onResult(data) }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        removeOnAttachStateChangeListener(attachListener)
    }
}

Использовать будет проще:


textView.doAsync({
    doSomeHeavyTask()
    "some text"
}) { text = it }
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации