Задачи в очереди с сопрограммами - PullRequest
1 голос
/ 16 апреля 2020

Я недавно начал читать о сопрограммах, и я хочу спросить об определенном сценарии.

Рассмотрим простой экран с одной кнопкой. При нажатии выполняется куча операторов печати и некоторые задержки (между). До сих пор я использую сопрограммы для достижения этой цели.

Теперь мой вопрос: если пользователь многократно спамит эту кнопку, есть ли способ поставить задачу в очередь и выполнить ее одну за другой (после предыдущего выполнение завершено) в выделенном потоке?

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        val thread = newSingleThreadContext("thread")

        binding.button1.setOnClickListener {

            CoroutineScope(thread).launch {
               Log.d("ABC", " TEXT1 ")
               delay(1000)
               Log.d("ABC", " TEXT2 ")
               delay(2000)
            }

        }

}

Теперь, если я выполню это, он будет работать нормально, и я смогу просмотреть журналы как таковые, если я нажму кнопку один раз:

TEXT1
TEXT2

Однако, если я спамлю кнопку, это то, что я вижу:

TEXT1
TEXT1
TEXT2
TEXT1
TEXT2
TEXT2

В основном, что происходит в моем наблюдении, когда пользователь нажимает кнопку, программа выполняется без любое ожидание или проверка. Итак, мой вопрос, как я могу отредактировать код так, чтобы, когда пользователь спамит кнопку, каждый куротин выполнялся последовательно, и каждый заканчивал работу до того, как следующий начинает выполняться, так что на выходе получается что-то вроде этого:

TEXT1
TEXT2
TEXT1
TEXT2
TEXT1
TEXT2

1 Ответ

0 голосов
/ 17 апреля 2020

Вы можете получить такое поведение с потоком независимо от того, какой поток или пул потоков вы используете:

class MyActivity : CoroutineScope by MainScope() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        val myFlow = callbackFlow {
            binding.button1.setOnClickListener {
                offer(Unit)
            }
            awaitClose()
        }

        launch(Dispatchers.Default) {
            myFlow
                .collect {
                    Log.d("ABC", " TEXT1")
                    delay(1000)
                    Log.d("ABC", " TEXT2")
                    delay(2000)
                }
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }
}
...