0Pricing
Kotlin Academy · บทเรียน

SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว

กำหนดค่า replay และ extraBufferCapacity ของ SharedFlow สำหรับกระจายเหตุการณ์

SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

SharedFlow คืออะไร

SharedFlow เป็นโฟลว์แบบร้อนที่กระจายข้อมูลไปยังผู้รวบรวมที่กำลังทำงานอยู่ทั้งหมด ต่างจาก StateFlow ตรงที่ไม่มีแนวคิดเรื่องค่าปัจจุบัน แต่ขับเคลื่อนด้วยเหตุการณ์เพียงอย่างเดียว

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val events = MutableSharedFlow<String>()
    launch { events.collect { println("Collector 1: $it") } }
    launch { events.collect { println("Collector 2: $it") } }
    delay(50)
    events.emit("UserLoggedIn")
    events.emit("DataRefreshed")
    delay(50)
    coroutineContext.cancelChildren()
}

พารามิเตอร์ replay

replay เก็บบัฟเฟอร์ของค่าที่ส่งออกล่าสุดจำนวน N ค่า ผู้รวบรวมรายใหม่จะได้รับเหตุการณ์ย้อนหลังสูงสุด N รายการทันที ค่าเริ่มต้นคือ 0 (ไม่ส่งเหตุการณ์ซ้ำ)

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>(replay = 2)
    flow.emit(1); flow.emit(2); flow.emit(3)
    // Late subscriber gets last 2:
    flow.collect { print("$it ") }  // prints 2 3
}

extraBufferCapacity

extraBufferCapacity เพิ่มพื้นที่บัฟเฟอร์นอกเหนือจาก replay ผู้ส่งสามารถส่งค่าออกได้โดยไม่ต้องระงับการทำงานจนกว่าบัฟเฟอร์จะเต็ม

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>(
        replay = 0,
        extraBufferCapacity = 10
    )
    // Can emit up to 10 times without a collector ready:
    repeat(10) { flow.tryEmit(it) }
    launch { flow.collect { print("$it ") } }
    delay(50)
    coroutineContext.cancelChildren()
}

tryEmit สำหรับการส่งออกโดยไม่ระงับการทำงาน

tryEmit(value) ส่งค่าออกโดยไม่ระงับการทำงาน และส่งกลับ false หากบัฟเฟอร์เต็ม ใช้ในบริบทที่ระงับการทำงานไม่ได้ เช่น callback หรือเครื่องจัดการการคลิก

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<String>(extraBufferCapacity = 5)
    val ok = flow.tryEmit("click")  // non-suspending
    println("Emitted: $ok")
    launch { flow.collect { println(it) } }
    delay(50)
    coroutineContext.cancelChildren()
}

เหตุการณ์แบบครั้งเดียว (การนำทาง UI)

ใช้ SharedFlow ที่มี replay=0 สำหรับเหตุการณ์ UI แบบครั้งเดียว เช่น การนำทางหรือการแสดงแถบข้อความชั่วคราว เหตุการณ์จะไม่ถูกส่งซ้ำเมื่อมีการจัดองค์ประกอบใหม่

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
class NavViewModel {
    private val _events = MutableSharedFlow<String>()
    val events = _events.asSharedFlow()
    fun navigateTo(route: String) {
        // viewModelScope.launch:
        kotlinx.coroutines.GlobalScope.launch { _events.emit(route) }
    }
}
// Collect in UI:
// viewModel.events.collect { route -> navController.navigate(route) }

SharedFlow เทียบกับ StateFlow

StateFlow: สถานะที่มีค่าปัจจุบัน (สถานะ UI) SharedFlow: เหตุการณ์ที่ไม่ถูกเก็บไว้ (การนำทาง แถบข้อความชั่วคราว การวิเคราะห์การใช้งาน) ให้เลือกตามว่าผู้ใช้ข้อมูลต้องการค่าล่าสุดหรือไม่

import kotlinx.coroutines.flow.*
// StateFlow: always has a value; new subscribers get current value
val uiState = MutableStateFlow("idle")

// SharedFlow: no stored value; events fire and are gone (unless replay>0)
val singleEvents = MutableSharedFlow<String>(replay = 0)

fun main() { println("State = what it is; Event = what happened") }

บัสเหตุการณ์ด้วย SharedFlow

สร้างบัสเหตุการณ์ระดับแอปแบบง่ายด้วย SharedFlow แบบซิงเกิลตัน เพื่อแทนรูปแบบการใช้งาน RxJava PublishSubject

import kotlinx.coroutines.flow.*
object EventBus {
    private val _events = MutableSharedFlow<Any>(extraBufferCapacity = 100)
    val events = _events.asSharedFlow()
    fun post(event: Any) { _events.tryEmit(event) }
}
sealed class AppEvent {
    object UserLoggedOut : AppEvent()
    data class ShowError(val msg: String) : AppEvent()
}
// Usage: EventBus.post(AppEvent.UserLoggedOut)

subscriptionCount

sharedFlow.subscriptionCount เป็น StateFlow ที่ติดตามจำนวนผู้รวบรวมที่กำลังทำงานอยู่ เหมาะสำหรับใช้เริ่มหรือหยุดตัวสร้างข้อมูลต้นทาง

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>()
    println("Subscribers: ${flow.subscriptionCount.value}")  // 0
    val job = launch { flow.collect { } }
    delay(50)
    println("Subscribers: ${flow.subscriptionCount.value}")  // 1
    job.cancel()
    delay(50)
    println("Subscribers: ${flow.subscriptionCount.value}")  // 0
}

resetReplayCache

resetReplayCache() ล้างแคชเหตุการณ์ย้อนหลังที่เก็บไว้ เหมาะเมื่อเหตุการณ์ที่ส่งซ้ำล้าสมัยและไม่ควรแสดงให้ผู้สมัครรับรายใหม่เห็น

import kotlinx.coroutines.flow.*
fun main() {
    val flow = MutableSharedFlow<Int>(replay = 3)
    flow.tryEmit(1); flow.tryEmit(2); flow.tryEmit(3)
    println("Replay cache: ${flow.replayCache}")  // [1, 2, 3]
    flow.resetReplayCache()
    println("Replay cache: ${flow.replayCache}")  // []
}

การจัดการแรงดันย้อนกลับใน SharedFlow

เมื่อตัวเก็บข้อมูลทำงานช้า ให้ใช้ onBufferOverflow เพื่อเลือกนโยบาย: SUSPEND (ค่าเริ่มต้น), DROP_OLDEST หรือ DROP_LATEST

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.channels.BufferOverflow
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>(
        replay = 0,
        extraBufferCapacity = 3,
        onBufferOverflow = BufferOverflow.DROP_OLDEST
    )
    repeat(10) { flow.tryEmit(it) }
    launch {
        flow.collect { println(it) }  // only sees most recent 3
    }
    delay(50)
    coroutineContext.cancelChildren()
}

การรวบรวมข้อมูลพร้อมการหมดเวลา

รวบรวมข้อมูลจาก SharedFlow พร้อมกำหนดการหมดเวลา เพื่อประมวลผลเหตุการณ์จำนวนจำกัดแล้วหยุด เหมาะสำหรับการทดสอบหรือการประมวลผลที่มีขอบเขต

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val events = MutableSharedFlow<String>()
    launch { repeat(5) { delay(50); events.emit("Event $it") } }
    withTimeoutOrNull(200) {
        events.collect { println(it) }
    }
    println("Done collecting")
}

ตรวจสอบอย่างรวดเร็ว

ควรใช้ค่า replay เท่าใดสำหรับเหตุการณ์ในส่วนติดต่อผู้ใช้ที่เกิดขึ้นครั้งเดียว เช่น การนำทาง

ทบทวน

SharedFlow เป็นตัวกระจายเหตุการณ์แบบร้อน ใช้ replay=0 สำหรับเหตุการณ์ที่เกิดขึ้นครั้งเดียว และใช้ replay>0 สำหรับผู้สมัครรับข้อมูลที่เข้ามาภายหลัง ใช้ tryEmit ในบริบทที่ระงับการทำงานไม่ได้ เลือก SharedFlow สำหรับเหตุการณ์ และ StateFlow สำหรับสถานะ

คำถามที่พบบ่อย

บทเรียน “SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว”

กำหนดค่า replay และ extraBufferCapacity ของ SharedFlow สำหรับกระจายเหตุการณ์ คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. StateFlow: ตัวเก็บสถานะแบบร้อนสำหรับ UI
  2. SharedFlow: บัสเหตุการณ์และเหตุการณ์แบบครั้งเดียว
  3. แปลง Cold Flow เป็น Hot ด้วย shareIn และ stateIn
  4. ทดสอบ StateFlow และ SharedFlow ด้วย Turbine
← กลับไปที่ Kotlin Academy