Kotlin Academy · Pelajaran

flowOn dan buffer: Context dan Backpressure

Ubah context emisi dengan flowOn dan simpan emisi dalam buffer untuk menangani backpressure.

Pelajaran 4 dari 413 langkah

flowOn dan buffer: Context dan Backpressure adalah pelajaran Kotlin Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Kotlin Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Kotlin Academy mencakup 4 pelajaran total.

Konteks Alur

Secara bawaan, alur berjalan dalam konteks coroutine yang memanggil collect. Dispetser produsen dan konsumen sama, kecuali 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 Hulu

flowOn(dispatcher) menjalankan alur hulu, yaitu semua bagian di atasnya dalam rangkaian, pada dispetser yang ditentukan, sedangkan pengumpulan tetap berjalan pada dispetser 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 Rangkaian

Anda dapat menggunakan flowOn beberapa kali. Setiap penggunaan memengaruhi operator yang berada tepat di atasnya hingga 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 Balik

Ketika produsen menghasilkan emisi lebih cepat daripada kemampuan pengumpul memprosesnya, nilai-nilai akan mengantre. Tanpa penyanggaan, hal ini menyebabkan produsen harus 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 produsen dan konsumen secara bersamaan dalam coroutine terpisah, lalu menyangga nilai yang dihasilkan di dalam kanal. Produsen tidak menunggu konsumen.

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")
    }
}

Kapasitas buffer

buffer(capacity) menetapkan ukuran penyangga kanal. Saat penyangga penuh, produsen ditangguhkan karena tekanan balik. Kapasitas bawaannya adalah 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 Terbaru Saja

conflate() membuang nilai perantara saat pengumpul berjalan lambat, dan hanya mempertahankan emisi terbaru. Ini berguna untuk status antarmuka 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 Lambat

collectLatest membatalkan blok pengumpulan saat ini ketika nilai baru tiba, lalu memulainya kembali dengan nilai terbaru.

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
    }
}

Pola flowOn + buffer

Gabungkan flowOn dan buffer: jalankan produsen pada IO untuk jaringan atau disk, sangga hasilnya, lalu kumpulkan pada dispetser 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 Produsen Konkuren

channelFlow membuat alur yang didukung oleh kanal, sehingga beberapa coroutine dapat menghasilkan emisi secara bersamaan dari dalam pembuatnya.

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 pergantian konteks, buffer untuk laju pemrosesan, conflate untuk antarmuka pengguna yang hanya membutuhkan nilai terbaru, dan collectLatest untuk membatalkan pemrosesan yang sudah usang.

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!") }

Pemeriksaan Singkat

Apa yang dipengaruhi flowOn dalam rangkaian alur?

Ringkasan

flowOn memindahkan pekerjaan hulu ke dispetser lain. buffer memisahkan produsen dan konsumen untuk meningkatkan laju pemrosesan. conflate membuang nilai perantara. collectLatest membatalkan pemrosesan lambat saat data baru tiba.

Gratis untuk memulai

Belajar Kotlin dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
51
Pelajaran
203

Pertanyaan yang Sering Diajukan

Apakah pelajaran “flowOn dan buffer: Context dan Backpressure” gratis?

Ya — teks lengkap “flowOn dan buffer: Context dan Backpressure” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Kotlin Academy, upgrade ke CoddyKit PRO. Kursus Kotlin Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “flowOn dan buffer: Context dan Backpressure”?

Ubah context emisi dengan flowOn dan simpan emisi dalam buffer untuk menangani backpressure. Kamu berlatih Kotlin Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Kotlin Academy?

Tidak diperlukan pengalaman sebelumnya. Kotlin Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “flowOn dan buffer: Context dan Backpressure” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Kotlin Academy ini?

Ya. Setiap pelajaran Kotlin Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

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