lifecycleScope — হল androidx.lifecycle লাইব্রেরি থেকে একটি বিল্ট-ইন CoroutineScope, যা Activity, Fragment বা যেকোনো LifecycleOwner-এর জীবনচক্রের সাথে সংযুক্ত এবং উপাদানটি ধ্বংস হলে স্বয়ংক্রিয়ভাবে করুটিন বাতিল করে। Google Android Developers, 2025 অনুসারে, lifecycleScope Activity বা Fragment ধ্বংস হওয়ার পর কোড সম্পাদনের ঝুঁকি ছাড়াই UI স্তরের সাথে সম্পর্কিত করুটিন নিরাপদে চালানোর অনুমতি দেয়। LifecycleOwner DESTROYED অবস্থায় রূপান্তরিত হলে scope স্বয়ংক্রিয়ভাবে বাতিল হয়ে যায়।
মূল পয়েন্ট
lifecycleScope হল LifecycleOwner ইন্টারফেসে (Activity, Fragment, Service) একটি এক্সটেনশন প্রপার্টি যা উপাদানের সম্পূর্ণ জীবনচক্রের সাথে সংযুক্ত একটি প্রস্তুত CoroutineScope প্রদান করে। যখন LifecycleOwner DESTROYED অবস্থায় পৌঁছায়, lifecycleScope স্বয়ংক্রিয়ভাবে সমস্ত সক্রিয় করুটিন বাতিল করে।
// In Fragment or Activity
lifecycleScope.launch {
delay(1000)
showSnackbar("হ্যালো!")
}
viewModelScope-এর বিপরীতে, lifecycleScope প্রতিবার LifecycleOwner ধ্বংস হওয়ার সময় বাতিল হয় — স্ক্রিন রোটেশন সহ। এটি এটিকে সেই অপারেশনগুলির জন্য আদর্শ করে তোলে যা কেবল তখনই চলা উচিত যখন একটি নির্দিষ্ট স্ক্রিন দৃশ্যমান থাকে।
lifecycleScope যেখানেই LifecycleOwner আছে সেখানেই উপলব্ধ:
lifecycleScope-এর স্বয়ংক্রিয় বাতিলকরণ প্রক্রিয়া Lifecycle ইভেন্টে সাবস্ক্রাইব করার উপর ভিত্তি করে। যখন Lifecycle CREATED থেকে নীচে DESTROYED-এ যায়, scope বাতিল হয়ে যায়।
| অবস্থা | বর্ণনা | Scope সক্রিয় |
|---|---|---|
| CREATED | LifecycleOwner তৈরি হয়েছে, onCreate সম্পাদিত হয়েছে | হ্যাঁ |
| STARTED | LifecycleOwner দৃশ্যমান (onStart) | হ্যাঁ |
| RESUMED | LifecycleOwner অগ্রভাগে (onResume) | হ্যাঁ |
| DESTROYED | LifecycleOwner ধ্বংস হয়েছে (onDestroy) | না (scope বাতিল) |
lifecycleScope CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) হিসাবে তৈরি করা হয় এবং Lifecycle-এর ভিতরে সংরক্ষণ করা হয়। যখন Lifecycle DESTROYED অবস্থায় রূপান্তরিত হয়, scope.cancel() কল করা হয়। প্রক্রিয়াটি LifecycleEventObserver-এর মাধ্যমে প্রয়োগ করা হয়, যা scope-এ প্রথম অ্যাক্সেসে জীবনচক্র ইভেন্টগুলিতে সাবস্ক্রাইব করে।
যখন স্ক্রিন ঘোরানো হয়, Activity ধ্বংস (onDestroy) হয় এবং পুনরায় তৈরি হয়। lifecycleScope পুরনো Activity-র সাথে বাতিল হয়ে যায়, এবং নতুন Activity-র জন্য scope-এর একটি নতুন উদাহরণ তৈরি করা হয়। এটি viewModelScope-এর থেকে মৌলিক পার্থক্য, যা রোটেশনে টিকে থাকে।
lifecycle লাইব্রেরি lifecycleScope-এর মাধ্যমে করুটিন চালু করার বিভিন্ন উপায় প্রদান করে। আসুন পুরনো পদ্ধতি থেকে আধুনিক API-তে বিবর্তন দেখি।
সবচেয়ে সহজ উপায় হল lifecycleScope.launch { ... }। করুটিন সঙ্গে সঙ্গেই শুরু হয় এবং DESTROYED-এ বাতিল হয়। তবে, এটি UI দৃশ্যমান না থাকলেও কোড সম্পাদন করতে পারে (যেমন, onStop-এর পর পটভূমিতে)। এটি সবসময় কাম্য নয়।
এই পদ্ধতিগুলি Lifecycle নির্দিষ্ট অবস্থার নীচে নেমে গেলে করুটিন সম্পাদন বিরাম দিত এবং ফিরে এলে পুনরায় শুরু করত। তবে, এগুলিকে lifecycle-runtime-ktx 2.6.0-এ @Deprecated হিসাবে চিহ্নিত করা হয়েছিল কারণ:
repeatOnLifecycle হল জীবনচক্রের সাথে সিঙ্ক্রোনাইজড করুটিন চালু করার Google-প্রস্তাবিত উপায়। এটি প্রতিবার Lifecycle নির্দিষ্ট অবস্থায় পৌঁছালে করুটিন বাতিল করে এবং পুনরায় চালু করে।
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
repeatOnLifecycle-এ পাস করা করুটিন শুরু হয় যখন Lifecycle STARTED-এ পৌঁছায় এবং যখন এটি STARTED-এর নীচে নেমে যায় তখন বাতিল হয়। STARTED-এ ফিরে এলে, করুটিন আবার শুরু হয়। এটি নিরাপদ এবং কার্যকর — কোনো করুটিন ঝুলন্ত থাকে না।
জীবনচক্র সচেতনতার সাথে Flow থেকে ডেটা সংগ্রহ করার জন্য, flowWithLifecycle অপারেটর রয়েছে। এটি Lifecycle অবস্থা পরিবর্তন হলে স্বয়ংক্রিয়ভাবে সংগ্রহ বন্ধ এবং পুনরায় শুরু করে:
viewModel.uiState
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.onEach { state -> updateUI(state) }
.launchIn(lifecycleScope)
flowWithLifecycle অপারেটরটি UI স্তরে Flow-এ নিরাপদে সাবস্ক্রাইব করার সবচেয়ে সংক্ষিপ্ত উপায়।
আসুন Kotlin-এ Android অ্যাপ্লিকেশনে lifecycleScope ব্যবহারের তিনটি বাস্তব পরিস্থিতি দেখি।
class MapFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
locationProvider.observeLocation().collect { loc ->
updateMapMarker(loc)
}
}
}
}
}
করুটিন শুরু হয় যখন ফ্র্যাগমেন্ট দৃশ্যমান হয় (STARTED) এবং স্ক্রিন ছেড়ে গেলে বাতিল হয় (STOPPED)। ব্যবহারকারী যদি অন্য অ্যাপে সুইচ করে, তবে লোকেশন আপডেট ব্যাটারি খরচ করে না।
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
animateFadeIn(titleView)
delay(200)
animateSlideUp(contentView)
}
}
অ্যানিমেশন কেবল তখনই চলে যখন ফ্র্যাগমেন্ট অগ্রভাগে থাকে (RESUMED)। ব্যবহারকারী যদি অ্যানিমেশনের সময় অ্যাপটি ছোট করে, করুটিন বাতিল হয়, এবং ফিরে এলে অ্যানিমেশন আবার শুরু হয়।
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
while (isActive) {
syncData()
delay(30_000L)
}
}
}
ডেটা প্রতি 30 সেকেন্ডে সিঙ্ক হয়, কিন্তু কেবল যখন স্ক্রিন দৃশ্যমান থাকে। isActive পরীক্ষা করে যে করুটিন বাতিল হয়েছে কিনা, যা স্ক্রিন ছেড়ে গেলে লুপ থেকে নিরাপদ প্রস্থান প্রদান করে।
উভয় scopeই জীবনচক্রের সাথে সংযুক্ত, তবে এর ভিন্ন দিকগুলির সাথে। পার্থক্য বোঝা Android অ্যাপ্লিকেশন আর্কিটেকচারের জন্য গুরুত্বপূর্ণ।
viewModelScope ViewModel-এর সাথে সংযুক্ত, যা স্ক্রিন রোটেশনে টিকে থাকে। lifecycleScope LifecycleOwner (Activity/Fragment)-এর সাথে সংযুক্ত, যা রোটেশনে ধ্বংস এবং পুনর্নির্মিত হয়। এটি তাদের ব্যবহারের পরিস্থিতি নির্ধারণ করে।
অনুশীলনে, উভয় scope-এর সংমিশ্রণ সাধারণ: viewModelScope ডেটা লোড করে এবং অবস্থা পরিচালনা করে, যখন lifecycleScope জীবনচক্র সচেতনতার সাথে ViewModel থেকে Flow-এ সাবস্ক্রাইব করে। দায়িত্বের এই পৃথকীকরণ আধুনিক Android ডেভেলপমেন্টে সেরা অনুশীলন হিসাবে বিবেচিত হয়।
আসুন lifecycleScope ব্যবহার করার সময় ডেভেলপারদের করা চারটি সবচেয়ে সাধারণ ভুল দেখি।
আপনি যদি lifecycleScope.launch-এ ডেটা লোডিং শুরু করেন, স্ক্রিন রোটেশনে করুটিন বাতিল হবে এবং ডেটা পুনরায় লোড করতে হবে। দীর্ঘস্থায়ী অপারেশনের জন্য viewModelScope ব্যবহার করুন। lifecycleScope কেবল UI-বাউন্ড কাজের জন্য।
lifecycleScope.launch-এর ভিতরে সরাসরি viewModel.someFlow.collect { ... } কল করা স্ক্রিন দৃশ্যমান না থাকলেও ডেটা সংগ্রহ চালিয়ে যায়। এটি পটভূমিতে UI আপডেট এবং অপ্রয়োজনীয় ওভারহেডের কারণ হতে পারে। সর্বদা repeatOnLifecycle বা flowWithLifecycle ব্যবহার করুন।
যদিও lifecycleScope DESTROYED-এ বাতিল হয়, হঠাৎ বাতিল হলে সাসপেন্ড পয়েন্টের পরের কোড সম্পাদিত নাও হতে পারে। যতক্ষণ না আপনি NonCancellable ব্যবহার করছেন, ততক্ষণ সাসপেন্ড কলের পর পোস্ট-কোড সম্পাদনের উপর নির্ভর করবেন না।
launchWhenStarted এবং এর সমতুল্যগুলি করুটিন বাতিল করে না, কেবল বিরাম দেয়। যদি স্ক্রিনটি একাধিকবার অগ্রভাগ এবং পটভূমির মধ্যে সুইচ করে, করুটিন স্থগিত কল জমা করে। repeatOnLifecycle-এ স্যুইচ করুন — Lifecycle-এর সাথে সিঙ্ক্রোনাইজ করার এটাই একমাত্র সঠিক উপায়।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
lifecycleScope LifecycleOwner ধ্বংস হলে স্বয়ংক্রিয়ভাবে বাতিল হয়। GlobalScope অ্যাপ্লিকেশনের পুরো সময় ধরে বেঁচে থাকে। lifecycleScope-এ করুটিন উপাদান ধ্বংস হওয়ার পর UI আপডেট করতে পারে না, GlobalScope-এ পারে, যা ক্র্যাশের দিকে নিয়ে যায়। UI স্তরে সর্বদা lifecycleScope ব্যবহার করুন।
না, ViewModel LifecycleOwner নয়, তাই এতে lifecycleScope উপলব্ধ নয়। ViewModel viewModelScope ব্যবহার করে। যদি কোড উভয় প্রসঙ্গে চলা উচিত, তবে লজিকটি suspend ফাংশন সহ use case বা repository-তে বের করে নিন।
repeatOnLifecycle-এর প্রতিটি কল একটি নতুন করুটিন তৈরি করে যা নির্দিষ্ট Lifecycle অবস্থায় পৌঁছালে ব্লক চালায়। যদি একই অবস্থার জন্য repeatOnLifecycle দুবার কল করা হয়, উভয় ব্লক স্বাধীনভাবে চলবে। সাধারণত onViewCreated-এ একটি কল যথেষ্ট।
আপনি সরাসরি lifecycleScope ডিসপ্যাচার পরিবর্তন করতে পারবেন না — এটি Dispatchers.Main.immediate ব্যবহার করে। করুটিন ব্লকের ভিতরে, আপনি withContext-এর মাধ্যমে অন্য ডিসপ্যাচারে স্যুইচ করতে পারেন। পরীক্ষার জন্য, LifecycleOwner-এর সাথে TestDispatcher ব্যবহার করুন।
lifecycleScope LifecycleOwner DESTROYED অবস্থায় (onDestroy-এর পর) রূপান্তরিত হলে বাতিল হয়। সাধারণ lifecycleScope.launch কল onPause বা onStop-এ বাতিল হয় না। পটভূমিতে যাওয়ার সময় বিরাম দিতে, repeatOnLifecycle(STARTED) বা repeatOnLifecycle(RESUMED) ব্যবহার করুন।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন