LifecycleOwner — এটি Android Jetpack লাইব্রেরির একটি মূল ইন্টারফেস যা ঘোষণা করে যে একটি অবজেক্টের একটি জীবনচক্র আছে এবং getLifecycle() পদ্ধতির মাধ্যমে এটিতে অ্যাক্সেস প্রদান করে। এটি আধুনিক Android অ্যাপ্লিকেশনের কম্পোনেন্ট আর্কিটেকচারের ভিত্তি, যা জীবনচক্র ব্যবস্থাপনার লজিককে Activity বা Fragment-এর নির্দিষ্ট বাস্তবায়ন থেকে আলাদা করতে দেয়। Google I/O 2024-এর তথ্য অনুযায়ী, Android-এর 85%-এর বেশি নতুন প্রকল্প LifecycleOwner ব্যবহার করে সাবস্ক্রিপশন পরিচালনা এবং মেমরি লিক প্রতিরোধ করে। এই ইন্টারফেসটি LiveData, ViewModel এবং Jetpack-এর অন্যান্য কম্পোনেন্টের ভিত্তি, যা কম্পোনেন্টের সক্রিয় অবস্থায় শুধুমাত্র কোডের নিরাপদ সম্পাদন নিশ্চিত করে।
মূল বিষয়
LifecycleOwner — এটি androidx.lifecycle প্যাকেজের একটি ইন্টারফেস যাতে একটি মাত্র পদ্ধতি getLifecycle() রয়েছে যা Lifecycle অবজেক্ট ফেরত দেয়। এই অবজেক্টটি কম্পোনেন্টের বর্তমান অবস্থা (CREATED, STARTED, RESUMED, DESTROYED) ট্র্যাক করে এবং পরিবর্তন হলে সমস্ত সাবস্ক্রাইব করা পর্যবেক্ষককে জানায়। LifecycleOwner আর্কিটেকচার কম্পোনেন্টসের অংশ এবং lifecycle-runtime লাইব্রেরিতে অন্তর্ভুক্ত।
ইন্টারফেসের প্রধান কাজ হল জীবনচক্রে অ্যাক্সেস মানকীকরণ। Jetpack আবির্ভাবের আগে, ডেভেলপাররা onStart-এ ম্যানুয়ালি সাবস্ক্রাইব এবং onStop-এ আনসাবস্ক্রাইব করত, যা কোডের পুনরাবৃত্তি এবং ত্রুটির কারণ হত। LifecycleOwner এই সমস্যার সমাধান করে, সমস্ত Android কম্পোনেন্টের জন্য একটি统一的 প্রক্রিয়া প্রদান করে। জীবনচক্র পদ্ধতি স্পষ্টভাবে কল করার পরিবর্তে, ডেভেলপার একবার Lifecycle-এ সাবস্ক্রাইব করে এবং বিজ্ঞপ্তিগুলি স্বয়ংক্রিয়ভাবে আসে।
ইন্টারফেসটি Kotlin-এ একটি কার্যকরী ইন্টারফেস হিসাবে ঘোষিত হয়েছে একটি বিমূর্ত পদ্ধতি সহ:
interface LifecycleOwner {
val lifecycle: Lifecycle
}
ইন্টারফেসের কার্যকরী প্রকৃতির কারণে, ডেলিগেট বা ল্যাম্বডা ব্যবহার করে এটি সহজেই বাস্তবায়ন করা যায়। এটি Custom Views এবং ViewModel ক্লাস তৈরির জন্য বিশেষভাবে সুবিধাজনক যা হোস্টের জীবনচক্র পরিবর্তনে সাড়া দিতে হবে। getLifecycle() থেকে প্রাপ্ত Lifecycle অবজেক্ট সাবস্ক্রিপশন পরিচালনার জন্য addObserver এবং removeObserver পদ্ধতি প্রদান করে।
LifecycleOwner দুটি মূল ক্লাসের সাথে কাজ করে: Lifecycle এবং LifecycleObserver। Lifecycle কম্পোনেন্টের বর্তমান অবস্থা enum State (INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED) আকারে সংরক্ষণ করে এবং তাদের মধ্যে স্থানান্তর ট্র্যাক করে। যখন অবস্থা পরিবর্তিত হয়, Lifecycle সমস্ত নিবন্ধিত পর্যবেক্ষককে জানায়, সংশ্লিষ্ট অ্যানোটেটেড পদ্ধতি কল করে। এই প্রক্রিয়াটিকে "lifecycle-aware" বলা হয় — কোড তখনই সম্পাদিত হয় যখন কম্পোনেন্ট উপযুক্ত অবস্থায় থাকে।
ইভেন্ট ট্রান্সমিশন প্রক্রিয়াটি Observer প্যাটার্নের উপর ভিত্তি করে। LifecycleOwner Observable হিসাবে কাজ করে, এবং LifecycleObserver বাস্তবায়ন Observer হিসাবে কাজ করে। Activity বা Fragment যখন তার অবস্থা পরিবর্তন করে (onCreate → onStart → onResume → onPause → onStop → onDestroy), তখন এটি ReportFragment-এর অভ্যন্তরীণ প্রক্রিয়ার মাধ্যমে Lifecycle-কে জানায়, যা AndroidX সিস্টেমে স্বয়ংক্রিয়ভাবে যোগ হয়। ডেভেলপারকে ম্যানুয়ালি Lifecycle পদ্ধতি কল করতে হয় না — সবকিছু স্বয়ংক্রিয়ভাবে ঘটে।
| Lifecycle অবস্থা | ইভেন্ট | Android জীবনচক্র পদ্ধতি |
|---|---|---|
| INITIALIZED | — | onCreate-এর আগে |
| CREATED | ON_CREATE | onCreate |
| STARTED | ON_START | onStart |
| RESUMED | ON_RESUME | onResume |
| STARTED | ON_PAUSE | onPause |
| CREATED | ON_STOP | onStop |
| DESTROYED | ON_DESTROY | onDestroy |
গুরুত্বপূর্ণ বিবরণ: Lifecycle গ্যারান্টি দেয় যে ON_STOP এবং ON_DESTROY ইভেন্ট প্রক্রিয়া ক্র্যাশের ক্ষেত্রেও পৌঁছে দেওয়া হবে। এটি LifecycleOwner-কে গুরুত্বপূর্ণ সম্পদ মুক্ত করার জন্য একটি নির্ভরযোগ্য টুল করে তোলে। সাধারণ অবস্থা সংরক্ষণের জন্য ViewModel-এ SavedStateHandle ব্যবহার করা সুপারিশ করা হয়, কিন্তু LifecycleOwner মৌলিক নিরাপত্তা স্তর নিশ্চিত করে।
LifecycleOwner-এ ইভেন্ট সাবস্ক্রাইব করার দুটি উপায় রয়েছে: ক্লাসিক LifecycleObserver অ্যানোটেশন সহ এবং আধুনিক DefaultLifecycleObserver স্পষ্ট পদ্ধতি সহ। দ্বিতীয় পদ্ধতিটি Google 2022 সাল থেকে সুপারিশ করে, কারণ এটি ভাল টাইপ-নিরাপত্তা প্রদান করে এবং রিফ্লেকশন এড়ায় যা অ্যানোটেশন পদ্ধতিতে ব্যবহৃত হত। DefaultLifecycleObserver-এর জন্য Java 8+ বা Kotlin প্রয়োজন এবং নতুন প্রকল্পের জন্য পছন্দনীয়।
DefaultLifecycleObserver-এর মাধ্যমে সাবস্ক্রিপশনের উদাহরণ:
class MyObserver : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
// GPS ট্র্যাকিং শুরু করুন শুধুমাত্র যখন কম্পোনেন্ট সক্রিয়
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
// ব্যাকগ্রাউন্ড মোডে যাওয়ার সময় নিরাপদ বন্ধ
stopLocationUpdates()
}
}
// সংযোগ:
lifecycleOwner.lifecycle.addObserver(MyObserver())
DefaultLifecycleObserver-এর প্রতিটি পদ্ধতি প্যারামিটার হিসাবে LifecycleOwner গ্রহণ করে। এটি পর্যবেক্ষককে আলাদাভাবে প্রেরণ না করেই চলমান কম্পোনেন্টের কনটেক্সট অ্যাক্সেস করতে দেয়। এই পদ্ধতি কোডকে আরও মডুলার এবং টেস্টযোগ্য করে তোলে — Observer Activity বা Fragment-এর নির্দিষ্ট বাস্তবায়নের উপর নির্ভর করে না, বরং LifecycleOwner অ্যাবস্ট্রাকশনের সাথে কাজ করে।
@OnLifecycleEvent অ্যানোটেশন সহ পুরানো পদ্ধতি এখনও লিগ্যাসি প্রকল্পে দেখা যায়, তবে নতুন কোডের জন্য এটি ব্যবহার করা সুপারিশ করা হয় না। অ্যানোটেশন প্রক্রিয়াকরণের জন্য প্রয়োজনীয় রিফ্লেকশন অতিরিক্ত ওভারহেড যোগ করে এবং এমন ত্রুটি সৃষ্টি করতে পারে যা কম্পাইলেশনের সময় ধরা পড়ে না। Google আনুষ্ঠানিকভাবে DefaultLifecycleObserver-এ মাইগ্রেট করার পরামর্শ দেয়।
// পুরানো পদ্ধতি — নতুন প্রকল্পের জন্য সুপারিশ করা হয় না
class MyLegacyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
startLocationUpdates()
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
stopLocationUpdates()
}
}
অ্যানোটেশন পদ্ধতির একটি উল্লেখযোগ্য ত্রুটি রয়েছে: Observer-এর জীবনকাল নিয়ন্ত্রণের অভাব। যদি ডেভেলপার LifecycleOwner ধ্বংস হলে Observer আনসাবস্ক্রাইব করতে ভুলে যায়, তাহলে Observer অবজেক্ট গার্বেজ কালেক্টর কল না করা পর্যন্ত মেমরিতে থাকে। DefaultLifecycleObserver এই সমস্যার সমাধান করে — Observer Lifecycle-এর সাথে আবদ্ধ হয় এবং DESTROYED অবস্থায় স্থানান্তরিত হলে স্বয়ংক্রিয়ভাবে আনসাবস্ক্রাইব হয়।
AppCompat 1.1.0 এবং AndroidX Fragment 1.2.0 থেকে, AppCompatActivity বা Fragment থেকে উত্তরাধিকারসূত্রে প্রাপ্ত সমস্ত Activity এবং Fragment স্বয়ংক্রিয়ভাবে LifecycleOwner হয়। এর অর্থ হল getLifecycle() পদ্ধতি ডিফল্টভাবে তাদের মধ্যে উপলব্ধ, এবং জীবনচক্র ইভেন্টে সাবস্ক্রিপশন অতিরিক্ত কনফিগারেশন ছাড়াই কাজ করে। ডেভেলপারকে শুধু Activity বা Fragment-এর যেকোনো জায়গা থেকে lifecycle.addObserver() কল করতে হবে।
Activity-তে LifecycleOwner ইন্টিগ্রেশনের উদাহরণ দেখি:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(LocationObserver(this))
}
}
এই উদাহরণে, lifecycle হল একটি extension property যা AndroidX Activity-র জন্য উপলব্ধ। LocationObserver পর্যবেক্ষক স্বয়ংক্রিয়ভাবে Activity-র স্টার্ট (ON_START) এবং স্টপ (ON_STOP) সম্পর্কে বিজ্ঞপ্তি পাবে। স্ক্রিন ঘোরানোর সময়, Observer ON_DESTROY এবং তারপর ON_CREATE সম্পর্কে বিজ্ঞপ্তি পায়, যা অতিরিক্ত কোড ছাড়াই কনফিগারেশন পরিবর্তনগুলি সঠিকভাবে পরিচালনা করতে দেয়।
Fragment ইন্টারফেসের মাধ্যমে LifecycleOwner বাস্তবায়ন করে, এবং এর Lifecycle প্যারেন্ট Activity-র পরিবর্তে Fragment-এর জীবনচক্রের সাথে আবদ্ধ। এটি গুরুত্বপূর্ণ: Fragment-এর Lifecycle তখনই DESTROYED-এ স্থানান্তরিত হয় যখন Fragment ট্রানজেকশন থেকে সরানো হয়, যখন Activity RESUMED অবস্থায় থাকতে পারে। এই পার্থক্য Observer-কে প্রতিটি কম্পোনেন্টের জীবনচক্রে আলাদাভাবে সাবস্ক্রাইব করতে দেয়।
class MyFragment : Fragment() {
private val uiStateObserver = UiStateObserver()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycle.addObserver(uiStateObserver)
}
}
Fragment-এ LifecycleOwner ব্যবহারের একটি গুরুত্বপূর্ণ সুবিধা হল Fragment DESTROYED-এ স্থানান্তরিত হলে স্বয়ংক্রিয় আনসাবস্ক্রিপশন। এটি ViewPager-এর জন্য বিশেষভাবে গুরুত্বপূর্ণ, যেখানে Fragment গতিশীলভাবে তৈরি এবং ধ্বংস হতে পারে। এই পরিস্থিতিতে ম্যানুয়াল সাবস্ক্রিপশন ব্যবস্থাপনা অত্যন্ত জটিল এবং ত্রুটিপূর্ণ হত।
LifecycleOwner ইন্টারফেসটি যেকোনো ক্লাসে বাস্তবায়ন করা যেতে পারে যার একটি জীবনচক্র আছে। এটি Custom Views, Services এবং কিছু আর্কিটেকচারাল সমাধানে ViewModel-এর জন্যও উপযোগী। Google সহায়ক ক্লাস LifecycleRegistry প্রদান করে যা Lifecycle-এর অবস্থা পরিচালনা করে এবং ইভেন্ট জেনারেট করে। কম্পোনেন্টের অবস্থা পরিবর্তনের সময় ডেভেলপারকে ম্যানুয়ালি LifecycleRegistry-র সংশ্লিষ্ট পদ্ধতি কল করতে হবে।
Custom View-এ LifecycleOwner বাস্তবায়নের উদাহরণ:
class MyCustomView(
context: Context,
attrs: AttributeSet?
) : FrameLayout(context, attrs), LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
override val lifecycle: Lifecycle
get() = lifecycleRegistry
fun onStart() {
lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED)
}
fun onStop() {
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED)
}
}
এই উদাহরণে, LifecycleRegistry অবস্থার ভান্ডার হিসাবে কাজ করে। onStart/onStop পদ্ধতিগুলি প্যারেন্ট কম্পোনেন্ট (যেমন, Activity) দ্বারা কল করা উচিত যখন Custom View দৃশ্যমান হয় বা লুকানো হয়। LifecycleRegistry স্বয়ংক্রিয়ভাবে অবস্থার মধ্যে স্থানান্তরের জন্য প্রয়োজনীয় ইভেন্ট গণনা করে এবং সমস্ত সাবস্ক্রাইব করা Observer-কে জানায়।
নিজস্ব LifecycleOwner বাস্তবায়নের সময় নিয়ম মেনে চলা গুরুত্বপূর্ণ: LifecycleRegistry-র অবস্থা সংশ্লিষ্ট জীবনচক্র পদ্ধতিতে শেষে আপডেট করা উচিত, অন্যান্য সমস্ত অপারেশনের পরে। এটি নিশ্চিত করে যে Observer বিজ্ঞপ্তি পায় যখন কম্পোনেন্ট ইতিমধ্যে নতুন অবস্থার জন্য সম্পূর্ণ প্রস্তুত। LifecycleRegistry.createUnsafe বিকল্প হিসাবে ব্যবহার করা সম্ভব, তবে থ্রেড নিয়ে সতর্কতা প্রয়োজন।
LifecycleOwner বেশ কয়েকটি মূল Android Jetpack কম্পোনেন্টের ভিত্তি। LiveData সক্রিয় অবস্থা নির্ধারণ এবং কম্পোনেন্ট ধ্বংস হলে স্বয়ংক্রিয় আনসাবস্ক্রিপশনের জন্য LifecycleOwner ব্যবহার করে। ViewModel সরাসরি LifecycleOwner বাস্তবায়ন করে না, কিন্তু SavedStateHandle-এর মাধ্যমে Lifecycle পেতে পারে। Navigation Component NavBackStackEntry-তে সাবস্ক্রিপশন পরিচালনার জন্য LifecycleOwner ব্যবহার করে। এই সম্পর্ক বোঝা একটি শক্ত ভিত্তির উপর অ্যাপ্লিকেশন আর্কিটেকচার তৈরি করতে সাহায্য করে।
LiveData এবং LifecycleOwner-এর মিথস্ক্রিয়া:
class ExampleActivity : AppCompatActivity() {
private val viewModel: ExampleViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.userData.observe(this) { data ->
// this — LifecycleOwner (Activity)
// কোড শুধুমাত্র তখনই সম্পাদিত হয় যখন Activity RESUMED অবস্থায় থাকে
updateUI(data)
}
}
}
LiveData-র observe() পদ্ধতিতে LifecycleOwner প্রয়োজন কারণ এটি নিশ্চিত করে যে UI আপডেট শুধুমাত্র সক্রিয় অবস্থায় ঘটবে। যদি Activity ব্যাকগ্রাউন্ডে থাকে, LiveData শেষ মান সংরক্ষণ করে কিন্তু Observer-কে জানায় না। RESUMED-এ ফিরে আসার সময়, Observer অতিরিক্ত নেটওয়ার্ক বা ডাটাবেস অনুরোধ ছাড়াই বর্তমান মান পায়।
DataBinding Activity বা Fragment-এর জীবনচক্রের সাথে observable ফিল্ড সংযুক্ত করতে LifecycleOwner ব্যবহার করে। এটি ViewModel + DataBinding সংমিশ্রণে মেমরি লিক এড়াতে দেয় — LifecycleOwner ধ্বংস হলে সমস্ত সাবস্ক্রিপশন স্বয়ংক্রিয়ভাবে পরিষ্কার হয়। এই পদ্ধতি কোডকে ঘোষণামূলক এবং নিরাপদ করে তোলে।
LifecycleOwner-এর সঠিক ব্যবহার বেশ কয়েকটি মূল নিয়ম মেনে চলা প্রয়োজন। প্রথম এবং সবচেয়ে গুরুত্বপূর্ণ: সর্বদা onCreate/onViewCreated-এ Observer সাবস্ক্রাইব করুন, পরে নয়। এটি নিশ্চিত করে যে Observer Lifecycle-এর প্রাথমিক অবস্থা (onCreate-এর পরে CREATED) পায় এবং ইভেন্ট মিস করে না। দ্বিতীয় নিয়ম: সমস্ত নতুন প্রকল্পের জন্য অ্যানোটেশন পদ্ধতির পরিবর্তে DefaultLifecycleObserver ব্যবহার করুন।
কোরুটিন এবং LifecycleOwner নিয়ে কাজ করার আধুনিক পদ্ধতি — repeatOnLifecycle এক্সটেনশন:
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.flow.collect { value ->
updateUI(value)
}
}
}
এই প্যাটার্নটি গ্যারান্টি দেয় যে Flow-তে collect শুধুমাত্র STARTED বা RESUMED অবস্থায় সক্রিয় থাকে। STOPPED-এ স্থানান্তরিত হলে, কালেকশন স্বয়ংক্রিয়ভাবে বাতিল হয়, এবং STARTED-এ ফিরে আসার সময় পুনরায় চালু হয়। repeatOnLifecycle Fragment-এ Flow থেকে ম্যানুয়াল আনসাবস্ক্রিপশন প্রতিস্থাপন করে এবং UI কম্পোনেন্টে অ্যাসিঙ্ক্রোনাস ডেটা স্ট্রিম নিয়ে কাজ করার জন্য Google-এর সুপারিশকৃত পদ্ধতি।
আরেকটি গুরুত্বপূর্ণ সুপারিশ: জীবনচক্রের সাথে সম্পর্কিত নয় এমন লজিকের জন্য LifecycleObserver ব্যবহার করবেন না। যদি একটি কম্পোনেন্ট নির্দিষ্ট অবস্থায় একটি কাজ সম্পাদন করতে হবে কিন্তু ধ্বংসের সময় আনসাবস্ক্রিপশনের প্রয়োজন না হয়, তাহলে onStart/onStop-এ স্পষ্ট পদ্ধতি কল ব্যবহার করা ভাল। LifecycleObserver দীর্ঘস্থায়ী কম্পোনেন্টের (LocationListener, SensorManager) জন্য উপযুক্ত যেখানে ম্যানুয়াল সাবস্ক্রিপশন ব্যবস্থাপনা জটিল এবং ত্রুটিপূর্ণ।
সচরাচর জিজ্ঞাসিত প্রশ্ন
LifecycleOwner — এটি একটি ইন্টারফেস যা ঘোষণা করে যে একটি অবজেক্টের একটি জীবনচক্র আছে। Lifecycle — এটি একটি ক্লাস যা বর্তমান অবস্থা সংরক্ষণ করে এবং Observer পরিচালনা করে। LifecycleOwner getLifecycle()-এর মাধ্যমে Lifecycle প্রদান করে।
না, Lifecycle DESTROYED-এ স্থানান্তরিত হলে স্বয়ংক্রিয়ভাবে সমস্ত Observer আনসাবস্ক্রাইব করে। এটি LifecycleOwner-এর একটি প্রধান সুবিধা — ডেভেলপারকে onDestroy-এ ম্যানুয়ালি removeObserver কল করতে হয় না।
Fragment AndroidX ফ্রাগমেন্ট ইন্টারফেসের মাধ্যমে LifecycleOwner বাস্তবায়ন করে। এর Lifecycle Fragment-এর জীবনচক্রের সাথে পৃথকভাবে Activity থেকে আবদ্ধ। এটি Observer-কে প্যারেন্ট Activity-র পরিবর্তে Fragment-এর ইভেন্টে সাড়া দিতে দেয়।
হ্যাঁ, এর জন্য LifecycleRegistry ব্যবহার করা হয়। Custom View-কে LifecycleOwner ইন্টারফেস বাস্তবায়ন করতে হবে এবং দৃশ্যমানতা বা উইন্ডোতে সংযুক্তি পরিবর্তনের সময় LifecycleRegistry-র অবস্থা ম্যানুয়ালি আপডেট করতে হবে।
LifecycleOwner একটি ভিন্ন সমস্যা সমাধান করে: জীবনচক্র ইভেন্টে সাবস্ক্রিপশন ব্যবস্থাপনা, কোরুটিন বাতিল করা নয়। কোরুটিনের জন্য lifecycleScope ব্যবহার করা হয় যা LifecycleOwner ধ্বংস হলে চলমান কোরুটিন স্বয়ংক্রিয়ভাবে বাতিল করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন