15

Flow؛ جریان داده مثل شیر آب کنترل‌شده

وقتی داده یکی‌یکی و در طول زمان میاد، Flow می‌گه بده به من مرتبش کنم.

درس 15 از 20

Flow برای چند مقدار async

تابع suspend معمولاً یک مقدار برمی‌گردونه؛ Flow می‌تونه چند مقدار رو در طول زمان منتشر کنه. مثل پخش زنده‌ی داده‌ها؛ نه یک عکس ثابت.

مثال را با چند مقدار دیگر هم امتحان کن؛ چون برنامه‌نویسی با نگاه کردن یاد گرفته نمی‌شود، با خراب کردن و درست کردن جا می‌افتد.

flow ساده
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun numbers(): Flow<Int> = flow {
    emit(1)
    emit(2)
    emit(3)
}

fun main() = runBlocking {
    numbers().collect { value ->
        println(value)
    }
}
خروجی یا نتیجه اجرا
1
2
3
نکته کاربردی: این بخش اسکلت ذهنی درس را می‌سازد. وقتی بدانی این قطعه دقیقاً چه مسئله‌ای را حل می‌کند، بعداً موقع پروژه فقط syntax حفظی تحویل نمی‌دهی؛ تصمیم درست می‌گیری. اگر خروجی با چیزی که انتظار داشتی فرق کرد، اول مقدار متغیرها و مسیر اجرا را چک کن؛ ۹۰٪ باگ‌های اول راه همین‌جا قایم شده‌اند.

transform با map و filter

Flow هم مثل collectionها `map` و `filter` داره، فقط async و مرحله‌ای کار می‌کنه. داده میاد، صاف می‌شه، خوشگل می‌شه، می‌رسه به UI.

مثال را با چند مقدار دیگر هم امتحان کن؛ چون برنامه‌نویسی با نگاه کردن یاد گرفته نمی‌شود، با خراب کردن و درست کردن جا می‌افتد.

map/filter
numbers()
    .filter { it % 2 == 1 }
    .map { it * 10 }
    .collect { println(it) }
خروجی یا نتیجه اجرا
10
30
نکته کاربردی: اینجا باید به رفتار کد نگاه کنی، نه فقط ظاهرش. مقدارها را عوض کن و دوباره اجرا بگیر تا دستت بفهمد برنامه چطور واکنش نشان می‌دهد. اگر خروجی با چیزی که انتظار داشتی فرق کرد، اول مقدار متغیرها و مسیر اجرا را چک کن؛ ۹۰٪ باگ‌های اول راه همین‌جا قایم شده‌اند.

catch برای خطا

جریان داده ممکنه وسط راه خطا بده. با `catch` محترمانه هندلش کن؛ نذار برنامه با لگد بیفته بیرون.

مثال را با چند مقدار دیگر هم امتحان کن؛ چون برنامه‌نویسی با نگاه کردن یاد گرفته نمی‌شود، با خراب کردن و درست کردن جا می‌افتد.

catch
flow {
    emit(1)
    error("مشکل در دریافت داده")
}
.catch { e -> emit(-1) }
.collect { println(it) }
خروجی یا نتیجه اجرا
1
-1
نکته کاربردی: این الگو در پروژه واقعی زیاد تکرار می‌شود. از همین حالا تمیز و خوانا بنویس تا بعداً موقع دیباگ، خودت به خودت فحش ندهی. اگر خروجی با چیزی که انتظار داشتی فرق کرد، اول مقدار متغیرها و مسیر اجرا را چک کن؛ ۹۰٪ باگ‌های اول راه همین‌جا قایم شده‌اند.

نتیجه این درس 🎯

Flow برای داده‌هایی است که یکی‌یکی و در طول زمان می‌آیند. وقتی سرچ زنده، وضعیت شبکه، دیتابیس یا event داری، Flow از callbackهای شلخته نجاتت می‌دهد.

تمرین! 🧠

Flow بساز که اعداد ۱ تا ۵ را emit کند، فقط زوج‌ها را چاپ کن.

جواب تمرین
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    flow {
        for (i in 1..5) emit(i)
    }
    .filter { it % 2 == 0 }
    .collect { println(it) }
}
خروجی جواب
2
4