AsyncTask как котлин сопрограмма - PullRequest
0 голосов
/ 17 марта 2019

Типичное использование для AsyncTask: я хочу запустить задачу в другом потоке, и после того, как эта задача выполнена, я хочу выполнить некоторую операцию в моем потоке пользовательского интерфейса, а именно скрыть индикатор выполнения.

Задача должна быть запущена в TextureView.SurfaceTextureListener.onSurfaceTextureAvailable, и после ее завершения я хочу скрыть индикатор выполнения. Выполнение этого синхронно не работает, потому что это блокирует поток, создающий пользовательский интерфейс, оставляя экран черным, даже не показывая индикатор выполнения, который я хочу скрыть впоследствии.

Пока я использую это:

inner class MyTask : AsyncTask<ProgressBar, Void, ProgressBar>() {
    override fun doInBackground(vararg params: ProgressBar?) : ProgressBar {
        // do async
        return params[0]!!
    }

    override fun onPostExecute(result: ProgressBar?) {
        super.onPostExecute(result)
        result?.visibility = View.GONE
    }
}

Но эти классы за пределами уродливых, поэтому я хотел бы избавиться от них. Я хотел бы сделать это с соплинами kotlin. Я пробовал несколько вариантов, но ни один из них не работает. Скорее всего, я бы заподозрил:

runBlocking {
        // do async
}
progressBar.visibility = View.GONE

Но это не работает должным образом. Насколько я понимаю, runBlocking не запускает новый поток, как AsyncTask, что мне и нужно. Но, используя сопрограмму thread, я не вижу разумного способа получить уведомление о ее завершении. Кроме того, я также не могу поместить progressBar.visibility = View.GONE в новый поток, потому что только поток пользовательского интерфейса может выполнять такие операции.

Я действительно новичок в сопрограммах, поэтому я не совсем понимаю, чего мне здесь не хватает.

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

Вы можете запустить ProgressBar в основном потоке пользовательского интерфейса, используя сопрограмму для асинхронного выполнения вашей задачи.

Внутри вашего метода переопределения onCreate (),

GlobalScope.launch(Dispatchers.Main) { // Coroutine Dispatcher confined to Main UI Thread
    yourTask() // your task implementation
}

Вы можете инициализировать,

private var jobStart: Job? = null

В Kotlin объявление var означает, что свойство является изменяемым,Если вы объявите его как val, он неизменен, доступен только для чтения и не может быть переназначен.

Вне метода onCreate () yourTask () может быть реализован как функция приостановки, которая не блокируетглавная тема звонящего.

Когда функция приостанавливается в ожидании возврата результата, ее рабочий поток разблокируется для выполнения другими функциями.

private suspend fun yourTask() = withContext(Dispatchers.Default){ // with a given coroutine context
    jobStart = launch {
       try{
        // your task implementation
       } catch (e: Exception) {
             throw RuntimeException("To catch any exception thrown for yourTask", e)
      }
    }
  }

Для индикатора выполнения вы можете создать кнопкучтобы показать индикатор выполнения при нажатии кнопки.

buttonRecognize!!.setOnClickListener {
    trackProgress(false)
}

Вне onCreate (),

private fun trackProgress(isCompleted:Boolean) {
    buttonRecognize?.isEnabled = isCompleted // ?. safe call
    buttonRecognize!!.isEnabled // !! non-null asserted call

    if(isCompleted) {
        loading_progress_bar.visibility = View.GONE
    } else {
        loading_progress_bar.visibility = View.VISIBLE
    }
}

Дополнительный совет - проверить, действительно ли работает ваша сопрограммав другой теме, например.DefaultDispatcher-worker-1,

Log.e("yourTask", "Running on thread ${Thread.currentThread().name}")

Надеюсь, это полезно.

0 голосов
/ 17 марта 2019

Во-первых, вы должны запустить сопрограмму с launch(context), а не с runBlocking: https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html

Во-вторых, чтобы получить эффект onPostExecute, вы должны использовать

Activity.runOnUiThread (Runnable) или View.post (Runnable) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...