SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال
اضبط replay وextraBufferCapacity في SharedFlow لبث الأحداث.
SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ما هو SharedFlow؟
SharedFlow هو Flow ساخن يبث إلى جميع الجامعين النشطين. وبخلاف 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()
}الأحداث أحادية التنفيذ (التنقل في واجهة المستخدم)
استخدم SharedFlow مع replay=0 لأحداث واجهة المستخدم أحادية التنفيذ، مثل التنقل أو عرض Snackbar؛ فلا يُعاد تشغيل الأحداث عند إعادة التركيب.
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: حالة ذات قيمة حالية، مثل حالة واجهة المستخدم. SharedFlow: أحداث بلا تخزين دائم، مثل التنقل وSnackbar والتحليلات. اختر بينهما بناءً على حاجة المستهلكين إلى أحدث قيمة.
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 مفرد، لتحل محل أنماط PublishSubject في RxJava.
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 للحالة.
تعلم Kotlin مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 51
- الدروس
- 203
الأسئلة الشائعة
هل درس «SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال» مجاني؟
نعم — نص درس «SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ماذا ستتعلم في «SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال»؟
اضبط replay وextraBufferCapacity في SharedFlow لبث الأحداث. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟
لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟
نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- StateFlow: حاوية حالة ساخنة لواجهة المستخدم
- SharedFlow: حافلات الأحداث والأحداث أحادية الإرسال
- تحويل Flow البارد إلى ساخن باستخدام shareIn وstateIn
- اختبار StateFlow وSharedFlow باستخدام Turbine