
در کار با Kotlin Flow، یکی از رایجترین ابهامها، تفاوت بین Cold Flow و Hot Flow است؛ مخصوصاً زمانی که چند بخش مختلف از برنامه میخواهند به تغییرات یک مقدار واکنش نشان بدهند.
برای درک ساده و ماندگار این تفاوت، میتوانیم از یک مثال آموزشی استفاده کنیم:
👉 معلم خصوصی در مقابل کلاس درس
فرض کنید یک معلم خصوصی دارید.
هر بار که یک شاگرد جدید میآید، معلم از اول درس را برای همان شاگرد شروع میکند؛ حتی اگر همین مطالب را قبلاً برای شاگرد دیگری گفته باشد.
در دنیای Kotlin Flow، این دقیقاً رفتار Cold Flow است.
هر collect باعث شروع یک اجرای جدید میشود
منطق بالادستی Flow به ازای هر collector دوباره اجرا میشود
هیچ دادهای بین collectorها به اشتراک گذاشته نمیشود
side-effectها (مثل لاگ، خواندن دیتابیس، شبکه) تکرار میشوند
val coldFlow = flow { println("Flow started") emit(loadFromDatabase()) }
جمعآوری در دو جای مختلف:
launch { coldFlow.collect { println("Collector A: $it") } } launch { coldFlow.collect { println("Collector B: $it") } }
Flow started Flow started Collector A: data Collector B: data
📌 کد داخل Flow دو بار اجرا شده؛ درست مثل معلم خصوصی که برای دو شاگرد جداگانه، درس را از اول میگوید.
حالا یک کلاس درس را تصور کنید.
معلم یک بار تدریس میکند و همهی دانشآموزان همزمان گوش میدهند. ورود یا خروج دانشآموزها تأثیری روی خود تدریس ندارد.
این دقیقاً رفتار یک Hot Flow است.
تولید داده مستقل از collectorها انجام میشود
مقدارها بین همهی collectorها مشترک هستند
side-effect فقط یک بار اتفاق میافتد
چند collector میتوانند با خیال راحت همزمان گوش بدهند
val sharedFlow = MutableSharedFlow<Int>()
چند collector:
launch { sharedFlow.collect { println("Collector A: $it") } } launch { sharedFlow.collect { println("Collector B: $it") } }
ارسال مقدار:
sharedFlow.emit(1)
Collector A: 1 Collector B: 1
📌 مقدار یک بار تولید شده و به همه رسیده؛ درست مثل تدریس در کلاس.
ویژگی replay مشخص میکند که چند مقدار آخر برای collectorهای جدید نگه داشته شود.
replay = 0)مثل کلاس زنده بدون ضبط:
اگر دانشآموز دیر برسد، مطالب قبلی را از دست میدهد
MutableSharedFlow<Int>(replay = 0)
replay = 1مثل کلاسی که آخرین اسلاید هنوز روی تخته است:
MutableSharedFlow<Int>(replay = 1)
هر collector جدید بلافاصله آخرین مقدار را دریافت میکند
replay = 2 (نگهداشتن تاریخچه رویداد)val flow = MutableSharedFlow<Int>(replay = 2)
این یعنی:
SharedFlow دو مقدار آخر ارسالشده را نگه میدارد و به هر collector جدید پخش میکند.
flow.emit(1) flow.emit(2) flow.emit(3)
بافر replay:
[2, 3]
یک collector جدید:
flow.collect { println(it) }
بلافاصله دریافت میکند:
2 3
حالا اگر مقدار جدیدی ارسال شود:
flow.emit(4)
همهی collectorهای فعال دریافت میکنند:
4
و بافر میشود:
[3, 4]
📌 این دقیقاً مثل کلاسی است که دو اسلاید آخر همیشه روی تخته باقی میماند.
StateFlow نوع خاصی از Hot Flow است که میتوان آن را به تختهی کلاس تشبیه کرد:
همیشه دقیقاً یک مقدار فعلی دارد
هر کسی وارد شود، فوراً آن مقدار را میبیند
val stateFlow = MutableStateFlow(0)
به همین دلیل، StateFlow بهترین انتخاب برای نمایش وضعیت (State) در UI است.
هر مصرفکننده اجرای مستقل میخواهد
عملیات یکباره (شبکه، محاسبه)
نیازی به اشتراک داده نیست
یک رویداد یا مقدار به چند بخش برنامه ارسال میشود
جلوگیری از اجرای تکراری
نیاز به replay رویدادها وجود دارد
نمایش وضعیت فعلی
UI باید فوراً آخرین مقدار را داشته باشد
به زبان ساده:
Cold Flow میگوید:
«برای هر نفر، از اول توضیح میدم.»
Hot Flow میگوید:
«دارم توضیح میدم، هر کی هست گوش بده.»
و با replay:
«اگر دیر اومدی، چند تا از مطالب قبلی اینجاست.»
درک این تفاوتها کمک میکند معماری تمیزتر، بهینهتر و قابل پیشبینیتری در برنامههای Kotlin و Android طراحی کنیم.
من محمد رئیسی برنامه نویس اندروید هستم و از توجهتون به ین پست سپاسگزارم.
ان شاءالله که مفید بوده باشه.