Kotlin Academy · Pelajaran

flowOn dan buffer: Context dan Tekanan Balik

Tukar context pancaran dengan flowOn dan tampan pancaran untuk menangani tekanan balik.

Pelajaran 4 daripada 413 langkah

flowOn dan buffer: Context dan Tekanan Balik ialah pelajaran Kotlin Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kotlin Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kotlin Academy merangkumi sejumlah 4 pelajaran.

Konteks Aliran

Secara lalai, aliran berjalan dalam konteks korutin yang memanggil collect. Penghantar pengeluar dan pengguna adalah sama melainkan anda mengubahnya.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    flow {
        println("emit on: ${Thread.currentThread().name}")
        emit(1)
    }.collect {
        println("collect on: ${Thread.currentThread().name}")
    }
}

flowOn Mengubah Konteks Huluan

flowOn(dispatcher) menjalankan aliran huluan, iaitu segala-galanya di atasnya dalam rantaian, pada penghantar yang ditentukan, manakala pengumpulan kekal pada penghantar pemanggil.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    flow {
        println("emit: ${Thread.currentThread().name}")
        emit(1)
    }.map {
        println("map: ${Thread.currentThread().name}")
        it * 2
    }.flowOn(Dispatchers.Default)  // above runs on Default
    .collect {
        println("collect: ${Thread.currentThread().name}")
    }
}

Beberapa flowOn dalam Satu Rantaian

Anda boleh menggunakan flowOn beberapa kali. Setiap satunya mempengaruhi operator yang terletak tepat di atasnya sehingga flowOn sebelumnya.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    flow { emit(1) }
        .map { it + 1 }.flowOn(Dispatchers.IO)      // map runs on IO
        .map { it * 2 }.flowOn(Dispatchers.Default)  // this map runs on Default
        .collect { println("Result: $it") }           // collect on Main (runBlocking)
}

Masalah Tekanan Balas

Apabila pengeluar menghasilkan keluaran lebih pantas daripada keupayaan pengumpul memprosesnya, nilai akan beratur. Tanpa penimbalan, keadaan ini menyebabkan pengeluar terpaksa menunggu.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val time = System.currentTimeMillis()
    flow {
        repeat(3) { i ->
            delay(100)  // fast producer
            emit(i)
        }
    }.collect {
        delay(300)      // slow consumer
        println("Got $it in ${System.currentTimeMillis() - time}ms")
    }
}

Operator buffer()

buffer() menjalankan pengeluar dan pengguna secara serentak dalam korutin berasingan, dengan menimbal nilai yang dihasilkan dalam saluran. Pengeluar tidak perlu menunggu pengguna.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val time = System.currentTimeMillis()
    flow {
        repeat(3) { i -> delay(100); emit(i) }
    }.buffer()  // producer and consumer run concurrently
    .collect {
        delay(300)
        println("Got $it in ${System.currentTimeMillis() - time}ms")
    }
}

Kapasiti buffer

buffer(capacity) menetapkan saiz penimbal saluran. Apabila penimbal penuh, pengeluar digantung, lalu menghasilkan tekanan balas. Kapasiti lalai ialah 64.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
    flow { repeat(5) { emit(it) } }
        .buffer(Channel.RENDEZVOUS)    // 0: producer waits
        // .buffer(Channel.BUFFERED)   // default: 64
        // .buffer(Channel.UNLIMITED)  // unbounded
        .collect { delay(50); println(it) }
}

conflate() untuk Nilai Terkini Sahaja

conflate() membuang nilai perantaraan apabila pengumpul berjalan perlahan dan hanya mengekalkan keluaran paling terkini. Ini berguna untuk keadaan antara muka pengguna.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    flow {
        repeat(5) { i -> emit(i); delay(50) }
    }.conflate()
    .collect { i ->
        delay(150)
        println("Collected: $i")  // skips some values
    }
}

collectLatest untuk Pengumpul Perlahan

collectLatest membatalkan blok pengumpulan semasa apabila nilai baharu tiba, kemudian memulakannya semula dengan nilai terkini.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    flow {
        emit(1); delay(50)
        emit(2); delay(50)
        emit(3)
    }.collectLatest { value ->
        println("Processing $value")
        delay(100)  // gets cancelled if new value arrives
        println("Done $value")  // only prints for last value
    }
}

Corak flowOn + buffer

Gabungkan flowOn dengan buffer: jalankan pengeluar pada IO, iaitu rangkaian atau cakera, simpan hasil dalam penimbal, dan lakukan pengumpulan pada penghantar utama.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun fetchItems(): Flow<String> = flow {
    repeat(3) { i ->
        delay(100)  // simulate IO
        emit("item-$i")
    }
}.flowOn(Dispatchers.IO).buffer(10)
fun main() = runBlocking {
    fetchItems().collect { println("UI: $it") }
}

channelFlow untuk Pengeluar Serentak

channelFlow mencipta aliran yang disokong oleh saluran, lalu membenarkan beberapa korutin menghasilkan keluaran secara serentak dari dalam pembina tersebut.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun concurrentFlow(): Flow<Int> = channelFlow {
    launch { send(1) }
    launch { send(2) }
    launch { send(3) }
}
fun main() = runBlocking {
    concurrentFlow().collect { println(it) }
}

Memilih Strategi yang Tepat

Ringkasan: flowOn untuk menukar konteks, buffer untuk kadar pemprosesan, conflate untuk antara muka pengguna yang hanya memerlukan nilai terkini, dan collectLatest untuk membatalkan pemprosesan yang sudah lapuk.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
// Guidelines:
// CPU-heavy production  -> flowOn(Dispatchers.Default)
// IO-heavy production   -> flowOn(Dispatchers.IO)
// Slow consumer         -> buffer()
// UI state updates      -> conflate() or StateFlow
// Search/autocomplete   -> collectLatest or flatMapLatest
fun main() = runBlocking { println("Choose the right strategy!") }

Semakan Ringkas

Apakah kesan flowOn dalam rantaian aliran?

Ulang Kaji

flowOn memindahkan kerja huluan kepada penghantar lain. buffer memisahkan pengeluar dan pengguna untuk meningkatkan kadar pemprosesan. conflate membuang nilai perantaraan. collectLatest membatalkan pemprosesan perlahan apabila ketibaan baharu berlaku.

Percuma untuk bermula

Pelajari Kotlin dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
51
Pelajaran
203

Soalan Lazim

Adakah pelajaran “flowOn dan buffer: Context dan Tekanan Balik” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Kotlin Academy, termasuk “flowOn dan buffer: Context dan Tekanan Balik”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Kotlin Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “flowOn dan buffer: Context dan Tekanan Balik”?

Tukar context pancaran dengan flowOn dan tampan pancaran untuk menangani tekanan balik. Anda berlatih Kotlin Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Kotlin Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Kotlin Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.

Berapa lamakah pelajaran “flowOn dan buffer: Context dan Tekanan Balik” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kotlin Academy ini?

Ya. Setiap pelajaran Kotlin Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Operator Flow: map, filter, transform dan take
  2. catch dan onCompletion: Pengendalian Error dalam Flow
  3. combine dan zip: Menggabungkan Berbilang Flow
  4. flowOn dan buffer: Context dan Tekanan Balik
← Kembali ke Kotlin Academy