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 সম্পূর্ণ না হয়া পর্যন্ত এক্সিকিউশন স্থগিত রাখে। একটি ব্যতিক্রমে সম্পূর্ণ হলে, 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 কোরোউটিনগুলোকে একটি ব্যর্থ হলেও চালু রাখতে দেয় — অগুরুত্বপূর্ণ অপারেশনের জন্য উপযোগী।
সামন্য প্রশ্নোত্তরি
পারে, কিন্তু এটি অর্থহীন। async বিনা await() এর একটি কোরোউটিন শুরু করে কিন্তু এর ফলাফল হারিয়ে যায়। যদি ফলাফলের প্রয়োজন না থাকে, তবে launch ব্যবহার করুন — এটি Deferred তৈরি করে না এবং মেমোরি এবং পারফরম্যান্সে আরও দক্ষ।
async এর মধ্যে একটি ব্যতিক্রম Deferred এ সংরক্ষিত হয়। await() কল করা এই ব্যতিক্রমকে ছুঁড়ে দেয়। ছুঁড়ে দেওয়া ছাড়া যাচাই করার জন্য getCompletionExceptionOrNull() ব্যবহার করুন। coroutineScope ব্যবহার করার সময়, একটি ত্রুটি সকল চাইল্ড কোরোউটিন বাতিল করে।
awaitAll() — Iterable<Deferred<T>> এর জন্য একটি বিস্তার ফাংশন যা সকল Deferred সম্পূর্ণ না হয়া পর্যন্ত কোরোউটিনকে স্থগিত রাখে। ফলাফলের একটি তালিকা ফেরত দেয়। একটি ব্যতিক্রমে ব্যর্থ হলে, এটি ব্যতিক্রম ছুঁড়ে দেয় এবং বাকিগুলো বাতিল করে।
হ্যাঁ। async, CoroutineScope এর একটি বিস্তার ফাংশন যা স্কোপের সাথে আবদ্ধ। GlobalScope.async জীবনচক্রের সাথে সংযুক্ত না হয়ে একটি কোরোউটিন তৈরি করে — এটি অসীমিতভাবে চলতে পারে। লিক এর ঝুঁকির কারণে Android এ GlobalScope সুপারিশ করা হয় না।
সংখ্যাটি ডিস্প্যাচার দ্বারা নির্ধারিত হয়: Dispatchers.IO 64 টি সমবর্তী থ্রেড পর্যন্ত সমর্থন করে, Dispatchers.Default — CPU কোরের সংখ্যা পর্যন্ত। ব্যচ অপারেশনের জন্য, Semaphore বা awaitAll এর সাথে mapNotNull এর মাধ্যমে সীমাবদ্ধ সমান্তরালতা ব্যবহার করুন।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন