async — Kotlin میں ایک Coroutine Builder ہے جو کوروٹین شروع کرتا ہے اور ایک غیر هم زمان کے آپریشن کا نتیجہ حاصل کرنے کے لیے Deferred<T> آبجیکٹ واپس کرتا ہے۔ async ایک ساتھ متعدد کاموں کو متوازی میں چلانے اور await() کے ذریعے ان کے نتائج کو اکٹھا کرنے کی اجازت دیتا ہے۔ JetBrains گائڈ، 2024 کے مطابق، async کوروٹینز میں متوازی حساب کارياں منظم کرنے کا ترجیحی طریقہ ہے۔
اہم نکات
async — CoroutineScope کا ایک اڤسٹنشن فنکشن ہے جو نتیجہ واپس کرنے والا کوروٹین تیار کرتا ہے۔ launch کے برعکس، async Deferred<T> واپس کرتا ہے — ایک آبجیکٹ جو مستقبل کی قیمت کی نمائندگی کرتا ہے۔ async کے ذریعے شروع کیا گیا ایک کوروٹین دوسرے کوروٹینز کے ساتھ ہم زمان چلتا ہے، حساب کاریاں کو متوازی کرنے کی اجازت دیتا ہے۔
async استعمال ہوتا ہے جب ایک غیر ہم زمان آپریشن کا نتیجہ مزید پروسینگ کے لیے ضروری ہوتا ہے: متعدد ذرائع سے ڈیٹا لوڈ کرنا، کلکشنز کی بیچ پروسینگ، مختلف API کو متوازی درخواستیں۔ Deferred فوری تیار ہوتا ہے، اور کوروٹین مکمل ہونے کے بعد نتیجہ دستیاب ہوتا ہے۔
import kotlinx.coroutines.*
suspend fun String.delayedValue(): String {
delay(1000L)
return this
}
fun main() = runBlocking {
val deferred: Deferred<String> = async { "Hello".delayedValue() }
println(deferred.await())
}
async کا دستخط launch کے مشابہ ہے: وہی CoroutineContext، CoroutineStart پیرامیٹر اور ایک suspend بلاک۔ فرق واپسی قیمت کی قسم میں ہے — Job کے بجاے Deferred<T>، جہاں T بلاک کے آخری ایکسپریشن سے واپس کیا گیا نتیجہ کی قسم ہے۔
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>
Deferred<T> — ایک اینٹرفیس جو Job سے وراستہ حاصل کرتا ہے اور await()، getCompleted()، getCompletionExceptionOrNull() میٹہڈ شامل کرتا ہے۔ await() ایک suspend فنکشن ہے اور صرف کوروٹین یا کسی دوسرے suspend فنکشن کے اندر بلایا جا سکتا ہے۔ getCompleted() ایک غیر منصرف کرنے والا میٹہڈ ہے جو اگر کوروٹین ابھی مکمل نہیں ہوئی تو استثنا پھینکتا ہے۔
async کا بیڑا فائدہ کاموں کو متوازی چلانے کی صلاحیت ہے۔ هر آپریشن کے لیے ایک تور پر انتظار کرنے کے بجائے (کل وقت = اوقات کا مجموعہ)، async کوروٹینز کو بایک ساتھ شروع کرتا ہے، کل وقت کو سب سے طویل آپریشن کی میاد تک کم کرتا ہے۔
ایک طریقی منظرنامہ — تین متوازی async درخواستوں کے ساتھ صارف کا پروفائل، ان کی ترتیبات اور آرڈر ہسٹری لوڈ کرنا۔ تینوں کے مکمل ہونے کے بعد، نتائج ایک واحد ڈیٹا ماڈل میں ملا دیئے جاتے ہیں۔
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
val profile = async { api.getProfile(userId) }
val settings = async { api.getSettings(userId) }
val orders = async { api.getRecentOrders(userId) }
Dashboard(
profile = profile.await(),
settings = settings.await(),
orders = orders.await()
)
}
coroutineScope فنکشن چائلڈ کوروٹینز شروع کرتا ہے اور نتیجہ واپس کرنے سے پہلے ان کے مکمل ہونے کا انتظار کرتا ہے۔ پورا بلاک ایک تور پر نہیں، بلکہ متوازی چلتا ہے۔
Deferred نتیجے کے ساتھ کام کرنے کے لیے متعدد میٹہڈ کی حمایت کرتا ہے۔ await() کے علاوہ، حالت چےک کرنے، مکمل قیمت حاصل کرنے اور Kotlin Coroutines کے مفید فنکشنز کے ذریعے متعدد Deferred کو اکٹھا کرنے کے میٹہڈ موجود ہیں۔
| میٹہڈ | تفصیل | Suspend؟ |
|---|---|---|
| await() | نتیجہ ملنے تک کوروٹین کو موقوف کرتا ہے | ہاں |
| getCompleted() | اگر کوروٹین مکمل ہو تو نتیجہ واپس کرتا ہے (ورنہ Exception) | نہیں |
| getCompletionExceptionOrNull() | غلطی پر استثنا یا null واپس کرتا ہے | نہیں |
| isCompleted | چےک کرتا ہے کہ کوروٹین مکمل ہوئی ہے یا نہیں | نہیں |
Deferred کی فہرست کو اکٹھا کرنے کے لیے، awaitAll() استعمال ہوتا ہے — ایک فنکشن جو کلکشن میں تمام Deferred کے مکمل ہونے تک عمل کو موقوف کرتا ہے۔ اگر کم سے کم ایک Deferred ناکام ہوتا ہے، تو awaitAll() استثنا پھینکتا ہے۔
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
return coroutineScope {
val deferreds = requests.map { async { it() } }
deferreds.awaitAll()
}
}
async اور launch کے درمیان انتخاب اس بات پر منحصر ہے کہ کوروٹین کا نتیجہ ضروری ہے یا نہیں۔ launch Job واپس کرتا ہے اور fire-and-forget آپریشنز کے لیے موزوں ہے، async Deferred واپس کرتا ہے اور ڈیٹا واپس کرنے والے کاموں کے لیے استعمال ہوتا ہے۔ سین ٹیکس اور پیرامیٹرز کے لحاظ سے، بلڈر ایک جیسے ہیں۔
اہم قاعدہ: fire-and-forget کے لیے async کا استعمال کبھی نہ کریں۔ اگر کوروٹین کا نتیجہ ضروری نہیں ہے، تو launch استعمال کریں۔ async Deferred بنانے کا اوورہیڈ پیدا کرتا ہے، جو ایسے مناظر میں جائز نہیں ہے۔
Android میں، async ViewModel اور UseCases کے اندر متوازی آپریشنز کے لیے استعمال ہوتا ہے۔ طریقی مناظر: ایک ساتھ پروفائل اور نیوز فیڈ لوڈ کرنا، متعدد موسم کی سروسوں سے موسم حاصل کرنا، سرور کے ساتھ بیچ ڈیٹا سنکرونائیزیشن۔
class HomeViewModel : ViewModel() {
fun loadHomeScreen() {
viewModelScope.launch {
val userData = async(Dispatchers.IO) { repository.getUserData() }
val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
val notifications = async(Dispatchers.IO) { repository.getNotifications() }
val state = HomeState(
user = userData.await(),
news = newsFeed.await(),
unread = notifications.await()
)
_uiState.update { state }
}
}
}
غلطی کی علاوہگی کے لیے async کے ایک گروپ کو coroutineScope یا supervisorScope میں لپیٹنے کی سفارش کی جاتی ہے۔ supervisorScope باقی async کوروٹینز کو ایک کے ناکام ہونے پر بھی جاری رکھنے کی اجازت دیتا ہے — غیر اہم آپریشنز کے لیے مفید۔
اکثر پوچے جانے والے سوالات
کیا جا سکتا ہے، لیکن بےمعنی ہے۔ await() کے بغیر async ایک کوروٹین شروع کرتا ہے لیکن اس کا نتیجہ گوم ہو جاتا ہے۔ اگر نتیجہ ضروری نہیں ہے، تو launch استعمال کریں — یہ Deferred نہیں بناتا اور میمری اور کارکردگی میں زیادہ موثر ہے۔
async کے اندر ایک استثنا Deferred میں محفوظ ہو جاتا ہے۔ await() کو کال کرنا اس استثنا کو پھینکتا ہے۔ بغیر پھینکے چےک کرنے کے لیے getCompletionExceptionOrNull() استعمال کریں۔ coroutineScope استعمال کرتے وقت، ایک غلطی تمام چائلڈ کوروٹینز کو منسوخ کر دیتی ہے۔
awaitAll() — Iterable<Deferred<T>> کے لیے ایک اڤسٹنشن فنکشن جو تمام Deferred کے مکمل ہونے تک کوروٹین کو موقوف کرتا ہے۔ نتائج کی فہرست واپس کرتا ہے۔ اگر کم سے کم ایک Deferred ناکام ہوتا ہے، تو یہ استثنا پھینکتا ہے اور باقی کو منسوخ کرتا ہے۔
ہاں۔ async CoroutineScope کا ایک اڤسٹنشن فنکشن ہے جو دائرہ سے منسلک ہے۔ GlobalScope.async لائف سائیکل سے منسلک ہوئے بغیر ایک کوروٹین بناتا ہے — یہ لا متناہی چل سکتا ہے۔ لیک کے خطرے کے باعث Android میں GlobalScope کی سفارش نہیں کی جاتی۔
تعداد ڈسپیچر کے ذریعے متعین ہوتا ہے: Dispatchers.IO انتہائی 64 بائی کام ساتھ چلنے والے دھاگے کی حمایت کرتا ہے، Dispatchers.Default — CPU کوریں کی تعداد تک۔ بلک آپریشنز کے لیے، Semaphore یا awaitAll کے ساتھ mapNotNull کے ذریعے محدود متوازیت استعمال کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں