Suspend function হল suspend মডিফায়ার সহ একটি ফাংশন যা থ্রেড ব্লক না করে তার নির্বাহ থামাতে পারে এবং পরে একই কোরুটিনে পুনরায় শুরু করতে পারে। JetBrains Kotlin Docs, 2025 অনুসারে, সাসপেন্ড ফাংশনগুলি কোরুটিনের মৌলিক বিল্ডিং ব্লক, যা কলব্যাক ছাড়াই অ্যাসিঙ্ক্রোনিসিটি প্রদান করে। প্রতিটি সাসপেন্ড ফাংশন Continuation-এর ভিত্তিতে একটি স্টেট মেশিনে কম্পাইল হয়, যা সাসপেনশন পয়েন্টগুলির কার্যকর ব্যবস্থাপনা সক্ষম করে।
মূল পয়েন্ট
Suspend function হল suspend কীওয়ার্ড দিয়ে ঘোষিত একটি ফাংশন যা থ্রেড ব্লক না করে এক বা একাধিক পয়েন্টে নির্বাহ থামাতে পারে। অন্য সাসপেন্ড ফাংশনের ভিতরে সাসপেন্ড ফাংশনের প্রতিটি কল একটি সম্ভাব্য সাসপেনশন পয়েন্ট।
suspend fun fetchUserData(): User {
val response = httpClient.get("/user")
return parser.parse(response)
}
Kotlin কম্পাইলার এই ধরনের ফাংশনকে স্টেট মেশিনে রূপান্তর করে। প্রতিটি সাসপেনশন পয়েন্ট (অন্য সাসপেন্ড ফাংশনের কল) একটি স্টেট (label) হয়ে যায়। বর্তমান থ্রেড স্টেটগুলির মধ্যে মুক্তি পায়, এবং অপেক্ষিত অপারেশন শেষ হওয়ার পরে, নির্বাহ পরবর্তী স্টেট থেকে পুনরায় শুরু হয়।
সাসপেন্ড ফাংশন Kotlin 1.3 (2018) এ কোরুটিনের সাথে একটি পরীক্ষামূলক বৈশিষ্ট্য হিসাবে আবির্ভূত হয় এবং Kotlin 1.5 (2021) এ স্থিতিশীল হয়। এর আগে, Kotlin/Java-এ অ্যাসিঙ্ক্রোনিসিটি কলব্যাক, RxJava এবং CompletableFuture-এর মাধ্যমে অর্জিত হত। সাসপেন্ড ফাংশন রৈখিক সিনট্যাক্স এবং স্বয়ংক্রিয় থ্রেড ব্যবস্থাপনার সাথে একটি বিকল্প প্রস্তাব করেছিল।
সাসপেন্ড ফাংশনের অভ্যন্তরীণ কার্যপ্রণালী বোঝা কোরুটিনের সাথে সঠিকভাবে কাজ করার চাবিকাঠি। সাধারণ ফাংশনের বিপরীতে, প্রতিটি সাসপেন্ড ফাংশন Continuation ইন্টারফেস সহ একটি ক্লাসে কম্পাইল হয়।
Kotlin কম্পাইলার প্রতিটি সাসপেন্ড ফাংশনের প্যারামিটার তালিকার শেষে Continuation টাইপের একটি প্যারামিটার যোগ করে। Continuation-এর মধ্যে রয়েছে:
ধরুন আমাদের কাছে দুটি অন্যান্য সাসপেন্ড ফাংশনের কল সহ একটি সাসপেন্ড ফাংশন আছে:
suspend fun process() {
val a = stepOne()
val b = stepTwo(a)
println(b)
}
কম্পাইলার এটিকে লেবেল সহ একটি স্টেট মেশিনে রূপান্তর করে:
// Simplified generated code representation
fun process(cont: Continuation<Unit>): Any? {
val cont = cont as ProcessContinuation
when (cont.label) {
0 -> {
cont.label = 1
if (stepOne(cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
}
1 -> {
cont.label = 2
val a = cont.result as TypeA
if (stepTwo(a, cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
}
2 -> {
println(cont.result)
Unit
}
}
}
মূল পর্যবেক্ষণ: যদি ফাংশন COROUTINE_SUSPENDED ফেরত দেয়, বর্তমান থ্রেড মুক্তি পায়। যখন অ্যাসিঙ্ক্রোনাস অপারেশন শেষ হয়, Continuation.resumeWith কল করা হয়, এবং স্টেট মেশিন পরবর্তী লেবেল থেকে অব্যাহত থাকে।
সাসপেন্ড ফাংশন ঘোষণা করা সাধারণ ফাংশন থেকে আলাদা নয়, শুধু fun-এর আগে suspend কীওয়ার্ড ছাড়া। শুধুমাত্র একটি সীমাবদ্ধতা আছে: সাসপেন্ড ফাংশন শুধুমাত্র কোরুটিন বা অন্য সাসপেন্ড ফাংশন থেকে কল করা যায়।
suspend fun delayAndReturn(ms: Long): String {
delay(ms)
return "Done after ${ms}ms"
}
এই উদাহরণে, delay একটি সাসপেন্ড ফাংশন যা থ্রেড ব্লক না করে নির্দিষ্ট মিলিসেকেন্ডের জন্য কোরুটিন থামায়। বিলম্বের পরে, নির্বাহ পুনরায় শুরু হয়।
fun main() = runBlocking {
val result = delayAndReturn(1000)
println(result)
}
runBlocking সাধারণ জগৎ এবং কোরুটিনের মধ্যে একটি সেতু তৈরি করে। lambda-এর ভিতরে, যেকোনো সাসপেন্ড ফাংশন কল করা যেতে পারে।
Kotlin কার্যকরী টাইপের সাসপেন্ড সংস্করণ সমর্থন করে — suspend () -> T এবং suspend (A) -> B. এটি উচ্চ-ক্রমের ফাংশনে অ্যাসিঙ্ক্রোনাস ল্যাম্বডা পাস করার অনুমতি দেয়:
suspend fun withRetry (
retries: Int = 3,
block: suspend () -> T
): T {
repeat(retries - 1) {
try { return block() }
catch (_: Exception) { delay(100) }
}
return block()
}
withRetry ফাংশন একটি সাসপেন্ড ল্যাম্বডা নেয় এবং ত্রুটিতে এর নির্বাহ পুনরায় চেষ্টা করে। এটি পুনরায় চেষ্টা সহ নেটওয়ার্ক অনুরোধের জন্য একটি সাধারণ প্যাটার্ন।
সাসপেন্ড এবং সাধারণ ফাংশনের মধ্যে পার্থক্য শুধু একটি মডিফায়ার যোগ করার বাইরে যায়। আসুন মূল পার্থক্যগুলি দেখি।
| বৈশিষ্ট্য | সাধারণ ফাংশন | সাসপেন্ড ফাংশন |
|---|---|---|
| নির্বাহ থ্রেড | শেষ পর্যন্ত থ্রেড ব্লক করে | থ্রেড ছেড়ে দিতে পারে এবং পরে পুনরায় শুরু করতে পারে |
| কম্পাইলার প্যারামিটার | শুধুমাত্র নির্দিষ্ট প্যারামিটার | শেষে অন্তর্নিহিত Continuation |
| সাধারণ ফাংশন থেকে কল | হ্যাঁ | না |
| স্ট্যাক | ভৌত থ্রেড স্ট্যাক | হিপে স্টেট মেশিন + পয়েন্টগুলির মধ্যে ভৌত স্ট্যাক |
| রিটার্ন মান | সরাসরি মান | মান বা COROUTINE_SUSPENDED |
| কর্মক্ষমতা | সর্বনিম্ন ওভারহেড | ~প্রতি স্টেট মেশিনে কয়েক ন্যানোসেকেন্ড (Kotlin 1.9+) |
সাধারণ ফাংশনে Continuation নেই — তার স্টেট সংরক্ষণের জায়গা নেই এবং নির্বাহ পুনরায় শুরু করার মতো কিছুই নেই। যদি আপনার সাধারণ ফাংশন থেকে সাসপেন্ড ফাংশন কল করার প্রয়োজন হয়, তাহলে runBlocking (পরীক্ষার জন্য) বা CoroutineScope.launch (জীবনচক্র সচেতনতা সহ উৎপাদনের জন্য) ব্যবহার করুন।
আসুন Kotlin দিয়ে Android অ্যাপে সাসপেন্ড ফাংশন ব্যবহারের তিনটি বাস্তব দৃশ্য দেখি।
Room সরাসরি সাসপেন্ড ফাংশন সমর্থন করে — কোয়েরি স্বয়ংক্রিয়ভাবে পটভূমি থ্রেডে নির্বাহিত হয়:
@Dao
interface UserDao {
@Query("SELECT * FROM users WHERE id = :id")
suspend fun getUser(id: Int): User?
@Insert
suspend fun insertUser(user: User)
}
Room অভ্যন্তরীণভাবে কোয়েরি নির্বাহের জন্য Dispatchers.IO ব্যবহার করে, এবং ফলাফল সেই ডিসপ্যাচারে ফেরত দেওয়া হয় যেখানে সাসপেন্ড ফাংশন কল করা হয়েছিল।
class ProfileViewModel : ViewModel() {
private val repo = ProfileRepository()
fun loadProfile(id: String) {
viewModelScope.launch {
val profile = repo.getProfile(id)
_profile.value = profile
}
}
}
ViewModelScope.launch একটি কোরুটিন তৈরি করে, যার ভিতরে getProfile সাসপেন্ড ফাংশন কল করা হয়। ফলাফল পাওয়ার পরে, UI প্রধান থ্রেডে আপডেট হয়।
suspend fun placeOrder(cart: Cart): OrderResult {
val validated = validateCart(cart)
val payment = processPayment(validated)
val receipt = sendReceipt(payment)
return receipt
}
তিনটি সাসপেন্ড ফাংশন ক্রমানুসারে নির্বাহিত হয়। প্রতিটি ধাপে, কোরুটিন থ্রেড ব্লক না করে থামতে পারে। যদি কোনো ধাপ ব্যতিক্রম নিক্ষেপ করে, বাকি ধাপগুলি নির্বাহিত হয় না, যা ভুল অর্ডার অবস্থা থেকে রক্ষা করে।
অভিজ্ঞ Kotlin ডেভেলপাররাও সাসপেন্ড ফাংশন ডিজাইন করার সময় ভুল করে। আসুন সবচেয়ে সাধারণ ভুলগুলো দেখি।
সাসপেন্ড ফাংশন কোডকে স্বয়ংক্রিয়ভাবে অ্যাসিঙ্ক্রোনাস করে না। Thread.sleep(), InputStream.read() এবং অন্যান্য ব্লকিং কল এখনও থ্রেড ব্লক করবে। ব্লকিং অপারেশন মোড়ানোর জন্য withContext(Dispatchers.IO) ব্যবহার করুন।
যদি একটি ফাংশন অন্য সাসপেন্ড ফাংশন কল না করে এবং অ্যাসিঙ্ক্রোনাস অপারেশন না করে — তাহলে সাসপেন্ড মডিফায়ার অপ্রয়োজনীয়। এটি স্টেট মেশিনের জন্য ওভারহেড যোগ করে এবং কলিং প্রসঙ্গ সীমাবদ্ধ করে। ফাংশনকে তখনই সাসপেন্ড বানান যখন এটি সত্যিই থামে।
যখন কোরুটিন বাতিল হয়, সাসপেন্ড ফাংশন CancellationException নিক্ষেপ করে। এটি চিন্তা না করে ধরা দেবেন না — আপনি কলিং কোডকে সঠিকভাবে বাতিলকরণ সম্পূর্ণ করার ক্ষমতা থেকে বঞ্চিত করছেন। যদি আপনার চূড়ান্তকরণ অপারেশন করার প্রয়োজন হয়, তাহলে finally ব্লক এবং NonCancellable ব্যবহার করুন।
suspend fun safeOperation() {
try {
doWork()
} finally {
withContext(NonCancellable) {
cleanup()
}
}
}
finally ব্লক সর্বদা নির্বাহিত হয়, বাতিলকরণেও, এবং NonCancellable নিশ্চিত করে যে পরিষ্কারকরণ ব্যাহত না হয়।
আপনি কোরুটিন তৈরি না করে সরাসরি কলব্যাক থেকে সাসপেন্ড ফাংশন কল করতে পারবেন না। কলব্যাক শৈলীকে কোরুটিনের সাথে খাপ খাওয়াতে suspendCoroutine বা suspendCancellableCoroutine ব্যবহার করুন।
সচরাচর জিজ্ঞাসিত প্রশ্ন
হ্যাঁ, প্রযুক্তিগতভাবে একটি সাসপেন্ড ফাংশন অন্যান্য সাসপেন্ড ফাংশন কল নাও করতে পারে। কম্পাইলার একটি একক স্টেট (label 0) সহ একটি স্টেট মেশিন তৈরি করবে। তবে, এই ধরনের ফাংশনের কোনো ব্যবহারিক সুবিধা নেই — এটি সাধারণ ফাংশনের মতো চলে কিন্তু ওভারহেড সহ। প্রয়োজন ছাড়া সাসপেন্ড ব্যবহার করবেন না।
Kotlin kotlinx-coroutines-debug প্রদান করে — DebugProbes এবং কোরুটিন ট্রেসিং টুল সহ একটি লাইব্রেরি। Android Studio-তে Arctic Fox থেকে, ডিবাগারে একটি অন্তর্নির্মিত Coroutines ট্যাব রয়েছে যা সক্রিয় কোরুটিন, তাদের অবস্থা এবং সাসপেনশন পয়েন্ট দেখায়।
প্রতিটি সাসপেনশন পয়েন্ট স্টেট মেশিনে একটি নতুন স্টেট তৈরি করে। অধিকাংশ অ্যাপ্লিকেশনের জন্য, একটি পয়েন্টের ওভারহেড কয়েক ন্যানোসেকেন্ড (Kotlin 1.9+)। শুধুমাত্র লুপে দশ হাজার পয়েন্টের সাথে আপনার অপারেশন একত্রিত করা বা sequence/flow ব্যবহার করার কথা বিবেচনা করা উচিত।
Kotlin-এ, suspend একটি ফাংশন টাইপ মডিফায়ার, রিটার্ন মান মার্কার নয় (যেমন C#-এ async)। যেকোনো সাসপেন্ড ফাংশনের যেকোনো প্যারামিটার এবং রিটার্ন টাইপ থাকতে পারে, এবং এর কল সিনট্যাক্টিকভাবে সাধারণ ফাংশন কল থেকে আলাদা নয় — কল সাইটে কোনো await অপারেটর নেই।
অভিযোজনের জন্য suspendCancellableCoroutine ব্যবহার করুন। ভিতরে, আপনি একটি কলব্যাক নিবন্ধন করেন যা continuation.resume() কল করে, এবং যদি কলব্যাক সাবস্ক্রিপশন বাতিল সমর্থন করে তবে একটি বাতিলকরণ টোকেন ফেরত দেন। এটি পুরানো Android API মোড়ানোর মানক প্যাটার্ন।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন