CoroutineScope — এটি কী, জীবনচক্র এবং করুটিনে কার্যপ্রণালী

লেখক: IT Sectr প্রকাশিত: 2026-06-22 পড়ার সময়: 10 মিনিট

CoroutineScope একটি Kotlin ইন্টারফেস যা করুটিনের জীবনচক্র নির্ধারণ করে এবং নতুন করুটিন চালানোর জন্য কনটেক্সট প্রদান করে। Kotlin ডকুমেন্টেশন, 2025 অনুসারে, প্রতিটি CoroutineScope ইনস্ট্যান্সে CoroutineContext থাকে এবং এর ভিতরে চালানো সমস্ত করুটিন পরিচালনা করে। যখন scope বাতিল (cancel) করা হয়, তখন সমস্ত চাইল্ড করুটিন স্বয়ংক্রিয়ভাবে বাতিল হয়ে যায়, যা মেমরি লিক প্রতিরোধ করে।

মূল পয়েন্ট

  • CoroutineScope — একটি মাত্র CoroutineContext ফিল্ড সম্বলিত ইন্টারফেস, যা করুটিনের জীবনচক্র নির্ধারণ করে
  • Job — বাতিলকরণের জন্য দায়ী কনটেক্সট উপাদান: scope বাতিল করলে সমস্ত চাইল্ড করুটিন বাতিল হয়
  • স্ট্রাকচার্ড কনকারেন্সি — নীতি যেখানে চাইল্ড করুটিন প্যারেন্ট scope-এর সাথে আবদ্ধ থাকে
  • GlobalScope — সম্পূর্ণ অ্যাপ্লিকেশনের জন্য scope যা মেমরি লিক ঝুঁকির কারণে সুপারিশ করা হয় না
  • supervisorScope — একটি বিশেষ scope যেখানে একটি চাইল্ড করুটিন বাতিল করলে অন্যগুলো বাতিল হয় না

Kotlin-এ CoroutineScope কী?

CoroutineScope kotlinx.coroutines লাইব্রেরির একটি মৌলিক ইন্টারফেস যা করুটিনের জন্য ধারক হিসেবে কাজ করে। এটি করুটিন জীবনচক্রের সীমানা নির্ধারণ করে: যখন scope সম্পূর্ণ হয়, তখন এর ভিতরের সমস্ত করুটিন স্বয়ংক্রিয়ভাবে বাতিল হয়ে যায়।

kotlin
public interface CoroutineScope {
    public val coroutineContext: CoroutineContext
}

ইন্টারফেসে শুধুমাত্র একটি ফিল্ড রয়েছে — coroutineContext। এর মাধ্যমে, scope এর ভিতরে চালানো সমস্ত করুটিনের জন্য একটি ডিসপ্যাচার (Dispatcher), জব (Job), এক্সেপশন হ্যান্ডলার এবং অন্যান্য কনটেক্সট উপাদান প্রদান করে।

kotlinx.coroutines লাইব্রেরিতে ভূমিকা

করুটিন চালানোর সমস্ত ফাংশন — launch, async, runBlocking — CoroutineScope-এ এক্সটেনশন ফাংশন। এর মানে হল এগুলো শুধুমাত্র scope অবজেক্ট উপলব্ধ থাকলেই কল করা যেতে পারে। এই ডিজাইন নিশ্চিত করে যে প্রতিটি করুটিনের একটি স্পষ্টভাবে সংজ্ঞায়িত প্যারেন্ট এবং জীবনচক্র রয়েছে।

CoroutineScope কোথায় ব্যবহৃত হয়

Android-এ, প্রতিটি আর্কিটেকচারাল কম্পোনেন্টের নিজস্ব scope থাকে: ViewModel-এর জন্য viewModelScope, Activity/Fragment-এর জন্য lifecycleScope। সার্ভার অ্যাপ্লিকেশনে, scope একটি HTTP রিকোয়েস্ট বা ডেটাবেস কানেকশন পুলের সাথে আবদ্ধ করা যেতে পারে।

CoroutineScope কীভাবে কাজ করে: Job এবং স্ট্রাকচার্ড কনকারেন্সি

CoroutineScope-এর অভ্যন্তরীণ কার্যপ্রণালী বোঝার জন্য Job-এর ধারণা এবং স্ট্রাকচার্ড কনকারেন্সি-র নীতির সাথে পরিচিতি প্রয়োজন।

Job — করুটিনের কাজ

প্রতিটি করুটিন চালু হওয়ার সময় একটি Job অবজেক্ট (বা async-এর জন্য Deferred) ফেরত দেয়। Job একটি সীমিত জীবনচক্র বিশিষ্ট কাজ উপস্থাপন করে: New, Active, Completing, Completed, Cancelling, Cancelled। Job অবজেক্টগুলো একটি ট্রি স্ট্রাকচার গঠন করে:

  • প্যারেন্ট Job — যে scope-এ করুটিন চালু করা হয়েছে
  • চাইল্ড Job — launch/async-এর মাধ্যমে চালু করা প্রতিটি করুটিন
  • প্যারেন্ট বাতিল → সমস্ত চাইল্ড বাতিল
  • চাইল্ডে এক্সেপশন → প্যারেন্ট বাতিল (supervisorScope ব্যতীত)

স্ট্রাকচার্ড কনকারেন্সির নীতি

স্ট্রাকচার্ড কনকারেন্সি Kotlin Coroutines-এর একটি মূল আর্কিটেকচারাল নীতি, যেখানে করুটিনের জীবনচক্র তার scope-এর জীবনচক্রের সাথে আবদ্ধ। এটি "ফায়ার-এন্ড-ফরগেট" মডেলের বিপরীত, যেখানে scope সম্পূর্ণ হওয়ার পরেও করুটিন বেঁচে থাকে। স্ট্রাকচার্ড কনকারেন্সির সুবিধা:

  • পূর্বাভাসযোগ্য জীবনচক্র — scope সম্পূর্ণ হলে, সমস্ত করুটিন বন্ধ হবে
  • স্বয়ংক্রিয় ত্রুটি ব্যবস্থাপনা — যেকোনো চাইল্ড করুটিনের এক্সেপশন scope-এ ছড়িয়ে পড়ে
  • কোনো মেমরি লিক নয় — scope সম্পূর্ণ হওয়ার পর কোনো করুটিন চলতে থাকে না
  • স্পষ্ট শ্রেণিবিন্যাস — কোড সমান্তরাল অপারেশনের যৌক্তিক কাঠামো প্রতিফলিত করে

CoroutineScope-এর জীবনচক্র

যখন scope.cancel() কল করা হয়, scope-এর Job Cancelled অবস্থায় চলে যায়, যা পুনরাবৃত্তিমূলকভাবে সমস্ত চাইল্ড Job বাতিল করে। বাতিলকরণের পরে, শুধুমাত্র নতুন CoroutineScope ইনস্ট্যান্স তৈরি করলেই scope পুনরায় ব্যবহার করা যেতে পারে।

CoroutineScope তৈরি এবং কনফিগারেশন

আপনি ফ্যাক্টরি ফাংশনের মাধ্যমে অথবা আপনার ক্লাসে ইন্টারফেস ইমপ্লিমেন্ট করে CoroutineScope তৈরি করতে পারেন। উভয় পদ্ধতি দেখি।

ফ্যাক্টরি ফাংশন CoroutineScope()

kotlin
val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

scope.launch {
    println("Running on ${Thread.currentThread().name}")
}

ফ্যাক্টরি ফাংশন একটি CoroutineContext গ্রহণ করে এবং নির্দিষ্ট কনটেক্সট সহ scope তৈরি করে। উদাহরণটি CPU-নিবিড় কাজের জন্য Dispatchers.Default এবং SupervisorJob ব্যবহার করে, যা চাইল্ড করুটিনের মধ্যে এক্সেপশন আলাদা করে।

কম্পোজিশনের মাধ্যমে ইন্টারফেস ইমপ্লিমেন্ট করা

kotlin
class MyRepository {
    private val scope = CoroutineScope(Dispatchers.IO + Job())

    suspend fun fetchData(): Data = scope.async {
        api.getData()
    }.await()

    fun cleanup() {
        scope.cancel()
    }
}

আমরা scope কে ক্লাস ফিল্ড হিসেবে সংরক্ষণ করি এবং এটি বাতিল করতে ম্যানুয়ালি cleanup কল করি। এই পদ্ধতি পরিচালিত জীবনচক্রযুক্ত কম্পোনেন্ট — যেমন রিপোজিটরি বা ম্যানেজার — এর জন্য উপযুক্ত।

ডেলিগেশনের মাধ্যমে ইমপ্লিমেন্টেশন

Kotlin by কীওয়ার্ডের মাধ্যমে CoroutineScope ইমপ্লিমেন্টেশন ডেলিগেট করার অনুমতি দেয়:

kotlin
class DataLoader : CoroutineScope by CoroutineScope(Dispatchers.IO) {
    fun load() {
        launch {
            // coroutine runs in DataLoader scope
        }
    }
}

এই পদ্ধতি সুবিধাজনক যখন ক্লাস নিজেই একটি scope এবং করুটিন চালু করার পদ্ধতি প্রদান করতে চায়। তবে সতর্ক থাকুন: ক্লাস CoroutineScope-এর সমস্ত পদ্ধতি ইনহেরিট করে, যার মধ্যে cancel-ও অন্তর্ভুক্ত, যা এনক্যাপসুলেশন ভাঙতে পারে।

GlobalScope বনাম কাস্টম CoroutineScope

GlobalScope সম্পূর্ণ অ্যাপ্লিকেশনের জন্য একটি সিঙ্গেলটন CoroutineScope। প্রোডাকশন কোডে এর ব্যবহার আনুষ্ঠানিকভাবে সুপারিশ করা হয় না।

GlobalScope-এর সমস্যা

  • স্ট্রাকচার্ড কনকারেন্সির অভাব — GlobalScope-এর করুটিন কম্পোনেন্ট জীবনচক্রের সাথে আবদ্ধ নয়
  • মেমরি লিক — Activity/Fragment বন্ধ হওয়ার পরেও করুটিন চলতে পারে
  • কঠিন পরীক্ষা — GlobalScope টেস্টে প্রতিস্থাপন করা যায় না
  • অনিয়ন্ত্রিত রিসোর্স খরচ — অনেক করুটিন প্রত্যাশার চেয়ে বেশি সময় ধরে চলতে পারে

GlobalScope কখন যথাযথ

JetBrains GlobalScope শুধুমাত্র বিরল পরিস্থিতিতে অনুমতি দেয়: অ্যাপ্লিকেশন-স্তরের ব্যাকগ্রাউন্ড প্রক্রিয়া যা সমস্ত Activity বন্ধ হওয়ার পরেও চলা উচিত (যেমন ডেটা সিঙ্ক্রোনাইজেশন, অ্যানালিটিক্স)। তবে এই ক্ষেত্রেও, CoroutineScope(SupervisorJob()) দিয়ে নিজস্ব scope তৈরি করা পছন্দনীয়।

সুপারিশ

সর্বদা কাস্টম CoroutineScope ব্যবহার করুন স্পষ্ট জীবনচক্র ব্যবস্থাপনা সহ। Android-এ, এগুলো হল viewModelScope এবং lifecycleScope। সার্ভার অ্যাপ্লিকেশনে, প্রতিটি রিকোয়েস্ট বা কানেকশন পুলের জন্য scope তৈরি করুন।

coroutineScope বনাম supervisorScope: পার্থক্য কী

উভয় ফাংশনই সাসপেন্ড ফাংশন যা সমান্তরাল কাজের জন্য অস্থায়ী scope তৈরি করে, কিন্তু এক্সেপশনের সাথে তাদের আচরণ মৌলিকভাবে ভিন্ন।

বৈশিষ্ট্যcoroutineScopesupervisorScope
ত্রুটিতে আচরণচাইল্ড করুটিনে এক্সেপশন বাকি সব বাতিল করেচাইল্ড করুটিনে এক্সেপশন অন্যগুলো বাতিল করে না
ত্রুটি প্রসারহ্যাঁ, প্রথম এক্সেপশন বাইরে ছড়িয়ে পড়েহ্যাঁ, প্রথম এক্সেপশন বাইরে ছড়িয়ে পড়ে
ডিফল্ট JobJob() — চাইল্ড প্যারেন্টের সাথে আবদ্ধSupervisorJob() — চাইল্ড একে অপরের উপর নির্ভরশীল নয়
সাধারণ ব্যবহার-ক্ষেত্রএকাধিক ধাপের পারমাণবিক অপারেশনস্বাধীন সমান্তরাল কাজ (UI লোড)

কখন coroutineScope বেছে নেবেন

coroutineScope ব্যবহার করুন যখন একাধিক সমান্তরাল অপারেশন একটি একক পারমাণবিক অপারেশন গঠন করে। উদাহরণস্বরূপ, তিনটি সার্ভার থেকে ডেটা লোড করা: যদি একটি রিকোয়েস্ট ব্যর্থ হয়, বাকিগুলো অর্থহীন।

kotlin
suspend fun loadProductPage(): ProductPage = coroutineScope {
    val product = async { api.getProduct() }
    val reviews = async { api.getReviews() }
    ProductPage(product.await(), reviews.await())
}

যদি getProduct বা getReviews এক্সেপশন ফেলে — উভয় করুটিন বাতিল হয়ে যায় এবং এক্সেপশন কলার কোডে ছড়িয়ে পড়ে।

কখন supervisorScope বেছে নেবেন

supervisorScope ব্যবহার করুন যখন সমান্তরাল অপারেশন একে অপরের উপর নির্ভরশীল নয়। উদাহরণস্বরূপ, একাধিক স্বাধীন বিভাগে প্রোফাইল ডেটা লোড করা: যদি রেকমেন্ডেশন বিভাগ ব্যর্থ হয়, প্রোফাইল হেডার এবং বন্ধু তালিকা প্রদর্শিত হওয়া উচিত।

CoroutineScope-এর সাথে কাজ করার সময় সাধারণ ভুল

Kotlin-এ CoroutineScope ব্যবহার করার সময় ডেভেলপারদের সবচেয়ে সাধারণ ভুলগুলো দেখি।

ভুল 1: Scope বাতিল করতে ভুলে যাওয়া

করুটিন লিকের সবচেয়ে সাধারণ পরিস্থিতি হল কম্পোনেন্ট শেষ হলে cancel কল না করে scope তৈরি করা। যদি scope বাতিল না করা হয়, করুটিন চলতে থাকে, অবজেক্টের রেফারেন্স ধরে রাখে। Android-এ, viewModelScope বা lifecycleScope ব্যবহার করুন, যা স্বয়ংক্রিয়ভাবে বাতিল হয়।

ভুল 2: Activity বা Fragment-এ GlobalScope ব্যবহার

GlobalScope Android কম্পোনেন্ট জীবনচক্র উপেক্ষা করে। Activity বন্ধ হওয়ার পর GlobalScope-এ চালু করা করুটিন চলতে থাকবে এবং UI আপডেট করার চেষ্টা করবে — যা ক্র্যাশের কারণ হবে। UI কম্পোনেন্টের জন্য সর্বদা lifecycleScope ব্যবহার করুন।

ভুল 3: বাতিল করা scope পুনরায় ব্যবহার

cancel() কল করার পর, scope পুনরায় ব্যবহার করা যায় না — এর ভিতরের সমস্ত করুটিন ইতিমধ্যে সম্পূর্ণ। ফ্যাক্টরি ফাংশনের মাধ্যমে নতুন CoroutineScope ইনস্ট্যান্স তৈরি করুন। Job() পুনরায় সক্রিয়করণ সমর্থন করে না।

ভুল 4: CoroutineScope ইন্টারফেসের ভুল ডেলিগেশন

by দিয়ে ডেলিগেট করলে, ক্লাস একটি পাবলিক cancel() পদ্ধতি পায় যা যেকোনো স্থান থেকে কল করা যেতে পারে, এনক্যাপসুলেশন ভেঙে। ইন্টারফেস ডেলিগেট করার পরিবর্তে scope কে প্রাইভেট ফিল্ড হিসেবে সংরক্ষণ করুন।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

CoroutineScope এবং CoroutineContext-এর মধ্যে পার্থক্য কী?

CoroutineScope একটি ইন্টারফেস যা CoroutineContext-এর মালিক এবং করুটিন জীবনচক্রের জন্য দায়ী। CoroutineContext হল উপাদানের (ডিসপ্যাচার, job, ত্রুটি হ্যান্ডলার) একটি সেট যা নির্ধারণ করে করুটিন "কীভাবে" সম্পাদিত হয়। একটি পার্থক্য: scope করুটিন তৈরি করে, যখন কনটেক্সট তাদের আচরণ নিয়ন্ত্রণ করে।

SupervisorJob দিয়ে কি CoroutineScope তৈরি করা যায়?

হ্যাঁ, এটি একটি স্ট্যান্ডার্ড প্যাটার্ন: CoroutineScope(Dispatchers.IO + SupervisorJob())। SupervisorJob একটি চাইল্ড করুটিনে এক্সেপশন হলে বাকিগুলোর ক্যাসকেডিং বাতিলকরণ প্রতিরোধ করে। এটি স্বাধীন সমান্তরাল কাজের জন্য উপযোগী যেখানে একটির ত্রুটি অন্যগুলো থামানো উচিত নয়।

CoroutineScope-এ কতগুলো করুটিন থাকতে পারে?

scope-এ করুটিনের কোনো সীমা নেই — এগুলো শুধুমাত্র উপলব্ধ মেমরি এবং ডিসপ্যাচার সেটিংস দ্বারা সীমিত। ব্যবহারিক সীমা সাধারণত একটি scope-এ হাজার হাজার সক্রিয় করুটিন। তবে, বিপুল সংখ্যক করুটিন আর্কিটেকচারাল সমস্যা নির্দেশ করতে পারে।

CoroutineScope-এর সাথে কোড কীভাবে পরীক্ষা করবেন?

সঠিক পদ্ধতি হল কনস্ট্রাক্টরের মাধ্যমে ক্লাসে scope পাস করা অথবা kotlinx-coroutines-test থেকে runBlockingTest / runTest ব্যবহার করা। পরীক্ষায়, আপনি scope কে TestCoroutineDispatcher দিয়ে প্রতিস্থাপন করতে পারেন এবং ম্যানুয়ালি করুটিন এক্সিকিউশন নিয়ন্ত্রণ করতে পারেন।

একটি করুটিনের কি নিজস্ব scope থাকতে পারে?

না, scope একটি করুটিনের জন্য বাহ্যিক ধারক। করুটিন নিজেই scope নয়। তবে, করুটিনের ভিতরে আপনি coroutineScope বা supervisorScope-এর মাধ্যমে চাইল্ড করুটিন সমান্তরালে চালানোর জন্য নতুন scope তৈরি করতে পারেন।

সারসংক্ষেপ

  • CoroutineScope — coroutineContext ফিল্ডযুক্ত ইন্টারফেস, যা এর ভিতরে চালিত করুটিনের জীবনচক্র নির্ধারণ করে
  • স্ট্রাকচার্ড কনকারেন্সি — scope বাতিল করলে স্বয়ংক্রিয়ভাবে সমস্ত চাইল্ড করুটিন বাতিল হয়, মেমরি লিক প্রতিরোধ করে
  • Job এবং SupervisorJob — ত্রুটি ব্যবস্থাপনার দুটি মোড: ক্যাসকেডিং বাতিলকরণ (Job) এবং বিচ্ছিন্ন ত্রুটি (SupervisorJob)
  • GlobalScope — জীবনচক্র বন্ধনের অভাবে প্রোডাকশনের জন্য সুপারিশ করা হয় না
  • coroutineScope বনাম supervisorScope — পারমাণবিক সমান্তরাল অপারেশন বনাম স্বাধীন সমান্তরাল কাজ
  • viewModelScope এবং lifecycleScope — Android-এর জন্য প্রস্তুত scopes, কম্পোনেন্ট শেষ হলে স্বয়ংক্রিয়ভাবে বাতিল
  • ফ্যাক্টরি ফাংশন — CoroutineContext + স্পষ্ট cancel কলের মাধ্যমে scope তৈরি করার পছন্দের উপায়

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন