مقدمه ای بر جریان ها

نسخه Kotlin از API های Home از جریان ها استفاده می کند، یکی از ویژگی های زبان Kotlin که قابلیت های قدرتمندی را برای مدیریت جریان های داده ناهمزمان، از جمله تبدیل، فیلتر کردن، نقشه برداری، تبدیل به و از مجموعه ها و غیره ارائه می دهد.

کوروتین‌ها ارتباط نزدیکی با جریان‌ها دارند و انتزاعی زیبا برای نوشتن کدهای ناهمزمان ارائه می‌کنند و توسعه‌دهنده را از نوشتن صریح روال‌های برگشت به تماس آزاد می‌کند. جریان ها دست به دست هم با کوروتین ها کار می کنند و به عنوان راهی برای بازیابی داده ها از کوروتین ها به صورت ناهمزمان، بدون نیاز به منتظر ماندن برای تکمیل یک تابع یا یک رشته، عمل می کنند.

داده ها از یک جریان توسط مصرف کننده در فرآیندی به نام جمع آوری بازیابی می شوند. جریان های Kotlin یک تابع collect() دارند که ممکن است برای این منظور استفاده شود. آنچه در یک جریان در طول جمع آوری اتفاق می افتد به نوع جریان بستگی دارد.

جریان‌های Kotlin ( Flow<T> ) به‌طور پیش‌فرض سرد هستند، به این معنی که کد سازنده جریان تنها زمانی داده‌ها را تولید می‌کند که collect() فراخوانی شود. در مقابل، یک جریان داغ ، داده‌ها را فوراً تولید می‌کند و آن‌ها را مانند یک صف برای هر زمان که داده مصرف می‌شود، در حافظه بافر نگه می‌دارد. از آنجا که داده ها را در حافظه نگه می دارد، یک جریان داغ حالتی در نظر گرفته می شود.

جریان ها ممکن است با استفاده از عملگر shareIn از سرد به گرم تبدیل شوند ( به گرم کردن جریان های سرد با استفاده از shareIn مراجعه کنید). همچنین می توانید از SharedFlow یا StateFlow برای تبدیل جریان سرد به جریان گرم استفاده کنید.

نحوه استفاده برنامه نمونه از جریان ها

برنامه نمونه از مدل‌های مشاهده در Jetpack Compose متصل به جریان‌های موجود در Home API استفاده می‌کند. بسیاری از عناصر رابط کاربری نمونه برنامه بر اساس وضعیت هدایت می شوند، اما می توان با آنها تعامل کرد. برنامه نمونه همچنین حالت‌های دستگاه‌ها را با حالت «خوش‌بینانه» در رابط کاربری ترکیب می‌کند تا تجربه کاربری بی‌درنگ داشته باشد. اصطلاح خوش‌بینانه به این معنی است که برنامه فرض می‌کند که یک اقدام معین موفقیت‌آمیز بوده است و بلافاصله رابط کاربری را به‌روزرسانی می‌کند تا نتیجه مورد انتظار را بدون منتظر ماندن برای تأیید منعکس کند. اگر معلوم شد که این عمل انجام نشد، رابط کاربری به‌روزرسانی می‌شود تا وضعیت واقعی را منعکس کند.

در برنامه نمونه، برای هر لایه از مدل view (ساختارها، اتاق ها، دستگاه ها) جریان ایجاد می شود. به عنوان مثال، این کار را برای ساختارهایی با فراخوانی زیر در GlobalViewModel.kt انجام می دهد:

  fun getStructuresState(): StateFlow<List<StructureModel>?> =
    homeClient
      .structures()
      .map { structures -> structures.map { StructureModel(it.name, it) }.sortedBy { it.name } }
      .handleErrors()
      .flowOn(Dispatchers.IO)
      .stateIn(scope = viewModelScope, started = SharingStarted.WhileSubscribed(), null)

emitAll() تمام مقادیر را از جریان داده شده جمع آوری می کند و آنها را به جمع کننده ارسال می کند. stateIn() آخرین مقدار منتشر شده را از یک نمونه در حال اجرا از جریان بالادستی با چندین مشترک پایین دستی به اشتراک می گذارد. برای اطلاعات بیشتر به مرجع kotlinx.coroutines.flow مراجعه کنید.

Jetpack Compose

برای ذخیره اشیاء جریان در حافظه محلی و جلوگیری از پایان یافتن آنها، از Kotlin remember API استفاده کنید.

در Jetpack Compose، اگر از آن با collectAsStateWithLifecycle() استفاده می‌کنید، Jetpack به‌طور خودکار اشتراک و لغو اشتراک از جریان‌ها را بر اساس اینکه رابط کاربری برنامه که آن حالت را واقعاً در پیش‌زمینه است یا خیر، مدیریت می‌کند.

یک تماس ساده در برنامه نمونه این کار را انجام می دهد. با استفاده از تابع getStructuresState() که قبلا نشان داده شد:

val structuresList by
    remember(globalViewModel) { globalViewModel.getStructuresState() }.collectAsStateWithLifecycle()

اکنون، هنگامی که هر حالتی برای ساختار تغییر می کند (مانند name )، تابع Composable که از آن استفاده می کند، آن حالت به روز شده را به طور خودکار منعکس می کند. در برنامه نمونه، این تابع HomeActivityContent() است.

منابع

برای اطلاعات بیشتر در مورد Kotlin، flows، coroutines و Jetpack Compose، به منابع زیر مراجعه کنید: