Android, как организовать сопрограммы элегантно? - PullRequest
0 голосов
/ 17 февраля 2019

Каков наилучший способ организовать сопрограммы для приложения элегантным способом?Я понимаю, вопрос кажется странным.Позвольте мне показать пример Executors

Создать объект AppExecutors.kt

object AppExecutors {

    private val main: Executor = MainThreadExecutor()
    private val util: Executor = Executors.newFixedThreadPool(3)

    fun main(f: () -> Unit) {
        main.execute(f)
    }

    fun util(f: () -> Unit) {
        util.execute(f)
    }

    class MainThreadExecutor : Executor {
        private val mainThreadHandler = Handler(Looper.getMainLooper())
        override fun execute(command: Runnable?) {
            mainThreadHandler.post(command)
        }
    }
}

Теперь мы можем использовать это.Простой минимальный код и т. Д.

val exe = AppExecutors
exe.util {
    val first = calculateFirst()
    val second = calculateSecond()
    val str = ("first = $first | second = $second")
    exe.main {
        Toast.makeText(activity, "Executors $str", Toast.LENGTH_LONG).show()
    }
}

Теперь я попытался использовать этот подход на сопрограммах AppCoRoutines.kt

object AppCoRoutines{
    private val uiContext: CoroutineContext = Dispatchers.Main
    private val ioContext: CoroutineContext = Dispatchers.IO
    private val networkContext: CoroutineContext = Executors.newFixedThreadPool(3).asCoroutineDispatcher()
    private val singleContext: CoroutineContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()

    val ui: CoroutineScope = CoroutineScope(uiContext)
    val io: CoroutineScope = CoroutineScope(ioContext)
    val net: CoroutineScope = CoroutineScope(networkContext)
    val single: CoroutineScope = CoroutineScope(singleContext)
}

Теперь используйте это:

val coRout = AppCoRoutines
coRout.ui.launch {
    val str: String = withContext(coRout.net.coroutineContext){
        val first = async { calculateFirst() }
        val second = async { calculateSecond() }
        ("first = $first | second = $second")
    }
    Toast.makeText(activity, "CoRoutine $str", Toast.LENGTH_LONG).show()
}

Не так уж и элегантно.Может быть, кто-то может предложить более простой способ?Сейчас я не очень хорош в этом, поэтому я использую сопрограммы для простых попыток.

Заранее спасибо!

1 Ответ

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

Вам нужно расширить CoroutineScope на сайте вызова (где бы вы ни хотели использовать свои сопрограммы, например, coRout.ui.launch в текущей реализации) ваших сопрограмм.Таким образом, вам не нужно писать и повторять coRout.ui.launch везде, а также вы можете избежать утечек памяти в текущем коде (поскольку ваши сопрограммы могут быть живыми, пока ваш вызывающий объект хочет быть уничтоженным)

Например, если вы находитесь внутри класса, вы можете сделать свой класс расширенным CoroutineScope, как показано ниже:

class SomeClass: CoroutineScope {
    val job = Job()
    override val coroutineContext: CoroutineContext
        get() = job + coRout.net.coroutineContext
}

Внутри этого класса вы можете использовать launch и withContext, чтобы легко обрабатывать ваши сопрограммы,Вы также можете cancel() job объект, когда вы знаете, что ваш класс уничтожается (например, onDestory для действий Android), так что все сопрограммы для этого класса будут отменены.

...