Jetpack Compose-এ লাইফসাইকেল   Android Jetpack-এর অংশ।

লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্ট হোস্ট অ্যাক্টিভিটির লাইফসাইকেল স্ট্যাটাসে পরিবর্তনের প্রতিক্রিয়ায় অ্যাকশন পারফর্ম করে। androidx.lifecycle.compose আর্টিফ্যাক্টটি ডেডিকেটেড API প্রদান করে যা স্ক্রিন থেকে চলে গেলে বা অ্যাপ্লিকেশনটি ব্যাকগ্রাউন্ডে চলে গেলে অটোমেটিক রিসোর্সগুলি পরিষ্কার করে।

গুরুত্বপূর্ণ API-এর মধ্যে এগুলি পড়ে:

  • বর্তমান Lifecycle.State-এর জন্য Flows।
  • LifecycleEffects, যা আপনাকে নির্দিষ্ট Lifecycle.Event-এর উপর ভিত্তি করে ব্লক রান করতে দেয়।

এইসব ইন্টিগ্রেশন Compose হায়ারার্কির মধ্যে লাইফসাইকেল ম্যানেজ করার জন্য সুবিধাজনক হুক প্রদান করে। এই ডকুমেন্ট থেকে আপনি জানতে পারবেন যে কীভাবে আপনার অ্যাপে এগুলি ব্যবহার করতে পারবেন।

ফ্লোর মাধ্যমে লাইফসাইকেল স্টেট সংগ্রহ করুন

লাইফসাইকেল একটি currentStateFlow প্রপার্টি প্রকাশ করে যা বর্তমান Lifecycle.State-কে Kotlin StateFlow হিসেবে প্রদান করে। আপনি এই Flow, State হিসেবে সংগ্রহ করতে পারবেন। এটি আপনার অ্যাপকে কম্পোজিশনের সময় লাইফসাইকেলে হওয়া পরিবর্তন পড়ার অনুমতি দেয়।

val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow
…
val currentLifecycleState by stateFlow.collectAsState()

lifecycle-common মডিউল ব্যবহার করে পূর্ববর্তী উদাহরণ অ্যাক্সেস করা যায়। currentStateAsState() পদ্ধতিটি lifecycle-runtime-compose মডিউলে উপলভ্য, যা আপনাকে একটি লাইনের মাধ্যমে বর্তমান লাইফসাইকেল স্টেট সুবিধাজনকভাবে পড়তে দেয়। নিম্নলিখিত উদাহরণে এটি দেখানো হয়েছে:

val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()

লাইফসাইকেল ইভেন্টে কোড রান করুন

DefaultLifecycleObserver ইমপ্লিমেন্ট করে এমন আলাদা ক্লাস তৈরি করা এবং ম্যানুয়ালি লাইফসাইকেলে যোগ করার পরিবর্তে, আপনি নির্দিষ্ট এফেক্ট ব্যবহার করে ইনলাইন লাইফসাইকেল লজিক ঘোষণা করতে পারেন। LifecycleEffects আপনাকে একটি ব্লক রান করতে দেয় যখন একটি নির্দিষ্ট Lifecycle.Event সরাসরি কম্পোজিশনের মধ্যে ঘটে।

LifecycleEventEffect

নির্দিষ্ট কোনও ইভেন্ট ঘটলে, কোডের ব্লক রান করতে LifecycleEventEffect ব্যবহার করুন। এটি লগিং বা অ্যানালিটিক্সের মতো ওয়ান-শট ইভেন্টের জন্য সবচেয়ে ভালো, যেখানে সাফল্য বা তাৎক্ষণিক ফলাফল, কোনওটিরই প্রয়োজন নেই।

@Composable
fun AnalyticsTracker(screenName: String) {
    // Log an event when the app receives ON_RESUME (e.g. comes to foreground)
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        Analytics.logView(screenName)
    }
}

LifecycleStartEffect

অ্যাপ চালু থাকাকালীন (দেখা যাচ্ছে) এবং অ্যাপ বন্ধ থাকাকালীন (ব্যাকগ্রাউন্ডে) ক্লিন-আপ করার জন্য পেয়ার করা স্টার্ট/স্টপ অপারেশন চালানোর জন্য, LifecycleStartEffect ব্যবহার করুন।

অন্যান্য Compose এফেক্টের (যেমন LaunchedEffect) মতো, LifecycleStartEffect কী গ্রহণ করে। কী পরিবর্তন হলে, এটি ব্লকটিকে আবার রান করার জন্য ট্রিগার করে।

যখন কোনও Lifecycle.Event.ON_STOP ইভেন্ট ঘটে বা এফেক্ট কম্পোজিশন থেকে বেরিয়ে যায়, তখন এটি onStopOrDispose ব্লক এক্সিকিউট করে যাতে স্টার্টিং ব্লকের অংশ ছিল এমন যেকোনও কাজ ক্লিন-আপ করা যায়।

@Composable
fun LocationMonitor(locationManager: LocationManager) {
    // Starts monitoring when ON_START is dispatched
    // Stops monitoring when ON_STOP is dispatched
    //   (or the composable leaves the screen)
    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { location ->
            /* update UI */
        }
        locationManager.requestLocationUpdates(listener)
        // The cleanup block automatically runs on ON_STOP or on disposal
        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
}
আপনার অপারেশনে যদি ক্লিন-আপের প্রয়োজন না হয়, তাহলে LifecycleEventEffect ব্যবহার করুন, Lifecycle.Event.ON_START পাস করুন।

অন্যান্য ধরনের সাইড-ইফেক্ট সম্পর্কে তথ্যের জন্য, Compose-এ সাইড-ইফেক্ট দেখুন।

LifecycleResumeEffect

LifecycleResumeEffect, LifecycleStartEffect-এর মতোই কাজ করে, তবে এটি Lifecycle.Event.ON_RESUME ইভেন্টের সাথে যুক্ত। এছাড়াও, এটি একটি onPauseOrDispose ব্লক প্রদান করে যা ON_PAUSE ডিসপ্যাচ করা হলে বা কম্পোজেবল স্ক্রিন থেকে চলে গেলে ক্লিনআপ করে।

এই API সেইসব রিসোর্সের জন্য উপযোগী যেগুলি ব্যবহারকারী অ্যাপের সাথে ইন্টার‍্যাক্ট করার সময় সক্রিয় থাকতে হয়—যেমন, ক্যামেরা বা অ্যানিমেশন।

@Composable
fun CameraPreview(cameraController: CameraController) {
    LifecycleResumeEffect(cameraController) {
        cameraController.startPreview()

        onPauseOrDispose {
            cameraController.stopPreview()
        }
    }
}

LifecycleOwner অ্যাক্সেস করুন

Compose-এ, LifecycleOwner LocalLifecycleOwner নামের CompositionLocal-এর মাধ্যমে ইমপ্লিসিটভাবে উপলভ্য। ডিফল্ট হিসেবে, আপনার কম্পোজিশন হায়ারার্কির রুট হোস্ট এই মালিকের তথ্য প্রদান করে।

val lifecycleOwner = LocalLifecycleOwner.current

অনেক অ্যাপের ক্ষেত্রে, এই ডিফল্ট মালিককে পরীক্ষা করা বা লাইফসাইকেল-অ্যাওয়ার ইফেক্টে পাস করাই যথেষ্ট। তবে, কাস্টম নেভিগেশন বা জটিল লেআউটের জন্য, আপনি UI-এর নির্দিষ্ট বিভাগে লাইফসাইকেল স্টেট স্কোপ করতে নিজের LifecycleOwner তৈরি করতে চাইতে পারেন। যেমন, নেভিগেশন লাইব্রেরি (যেমন Navigation 3) প্রতিটি স্বতন্ত্র স্ক্রিনকে নিজস্ব লাইফসাইকেল দিতে অটোমেটিক এটি করে।

কাস্টম LifecycleOwner তৈরি করা

rememberLifecycleOwner() API আপনাকে একটি কাস্টম LifecycleOwner তৈরি করতে এবং মনে রাখতে দেয়। এটি বিশেষ করে HorizontalPager-এর মতো কম্পোনেন্টের ক্ষেত্রে উপযোগী, যেখানে আপনি চান যে শুধু দৃশ্যমান, সেটেল করা পৃষ্ঠা RESUMED হোক, পাশাপাশি, অফ-স্ক্রিন পৃষ্ঠার জন্য STARTED-এর maxState সেট করা হোক।

val pagerState = rememberPagerState(pageCount = { 10 })

HorizontalPager(state = pagerState) { pageNum ->
    val pageLifecycleOwner = rememberLifecycleOwner(
        maxState = if (pagerState.settledPage == pageNum) {
            Lifecycle.State.RESUMED
        } else {
            Lifecycle.State.STARTED
        }
    )

    CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
        // Your pages here. Their lifecycle-aware components respect the
        // custom maxState defined above.
    }
}

CompositionLocal সম্পর্কে আরও তথ্যের জন্য, CompositionLocal-এর সাথে স্থানীয়ভাবে স্কোপ করা ডেটা দেখুন।

লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্টের জন্য পেশাদার পদ্ধতি

  • আপনার UI কন্ট্রোলার যতটা সম্ভব হালকা রাখুন। তাদের নিজেদের ডেটা পাওয়ার চেষ্টা করা উচিত নয়; পরিবর্তে, এটি করার জন্য একটি ViewModel ব্যবহার করুন, এবং UI-তে পরিবর্তনগুলি প্রতিফলিত করতে একটি StateFlow অবজেক্ট লক্ষ্য করুন।
  • ডেটা-চালিত UI লেখার চেষ্টা করুন যেখানে আপনার UI কন্ট্রোলারের দায়িত্ব হল ডেটা পরিবর্তনের সাথে সাথে UI আপডেট করা, বা ব্যবহারকারীর অ্যাকশন সম্পর্কে ViewModel-কে জানানো।
  • আপনার ডেটা লজিক ViewModel ক্লাসে রাখুন। ViewModel-কে আপনার UI কন্ট্রোলার এবং অ্যাপের বাকি অংশের মধ্যে কানেক্টর হিসেবে কাজ করতে হবে। তবে, ডেটা ফেচ করা (যেমন, নেটওয়ার্ক থেকে) ViewModel-এর দায়িত্ব নয়। পরিবর্তে, ViewModel-এর উচিত ডেটা আনার জন্য উপযুক্ত কম্পোনেন্টকে কল করা, তারপর UI কন্ট্রোলারকে ফলাফল প্রদান করা।
  • দীর্ঘ সময় ধরে চলা টাস্ক এবং অন্যান্য অপারেশন যা অ্যাসিঙ্ক্রোনাসভাবে চলতে পারে, তা ম্যানেজ করতে Kotlin coroutines ব্যবহার করুন।
  • কম্পোজেবলের মধ্যে শুরু/বন্ধ করার লজিক রাখুন যার আসলে এটি প্রয়োজন। এইভাবে, স্ক্রিন থেকে নির্দিষ্ট UI এলিমেন্ট সরিয়ে দেওয়া হলে লজিক অটোমেটিক সরিয়ে দেওয়া হয় (যেমন, নেভিগেশন গ্রাফের মধ্যে বা দৃশ্যমানতা শর্তসাপেক্ষ হলে)।
  • ডেটার জন্য collectAsStateWithLifecycle ব্যবহার করুন। লাইফসাইকেল ইভেন্টের উপর ভিত্তি করে Flow সংগ্রহ ম্যানুয়ালি শুরু বা বন্ধ করবেন না। পরিবর্তে, স্ট্রিমকে UI স্টেটে দক্ষতার সাথে কনভার্ট করতে collectAsStateWithLifecycle ব্যবহার করুন। এটি ব্যাটারি ও রিসোর্স বাঁচায় কারণ অ্যাপ ব্যাকগ্রাউন্ডে থাকলে Flow পজ করা থাকে।

Flow সম্পর্কে আরও তথ্যের জন্য, অন্যান্য কাজ করে এমন ধরনের রাজ্য দেখুন।

লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্টের ক্ষেত্রে সম্ভাব্য পরিস্থিতি

লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্ট বিভিন্ন ক্ষেত্রে লাইফসাইকেল ম্যানেজ করার কাজ আপনার জন্য অনেক সহজ করে দিতে পারে। কয়েকটি উদাহরণ হল:

  • মোটামুটি ও সূক্ষ্ম লোকেশন আপডেটের মধ্যে পরিবর্তন করা। আপনার অ্যাপ দৃশ্যমান থাকাকালীন (ON_START) ফাইন-গ্রেনড লোকেশন আপডেট চালু করতে LifecycleStartEffect ব্যবহার করুন এবং অ্যাপ ব্যাকগ্রাউন্ডে (ON_STOP) থাকলে অটোমেটিক লিসেনার ক্লিন-আপ করুন অথবা কোর্স-গ্রেনড আপডেটে পাল্টে নিন।
  • ভিডিও বাফারিং বন্ধ ও শুরু করা। অ্যাপটি সম্পূর্ণভাবে ফোরগ্রাউন্ডে না আসা এবং ইন্টার‍্যাক্টিভ (ON_RESUME) না হওয়া পর্যন্ত আসল ভিডিও প্লেব্যাক স্থগিত রাখতে LifecycleResumeEffect ব্যবহার করুন এবং অ্যাপটি ব্যাকগ্রাউন্ডে (ON_PAUSE) চলে গেলে প্লেব্যাক পজ করা এবং রিসোর্স রিলিজ করা নিশ্চিত করুন।
  • নেটওয়ার্ক স্ট্রিমিং শুরু ও বন্ধ করা। ডেটার অবিচ্ছিন্ন স্ট্রিম (যেমন নেটওয়ার্ক সকেট থেকে Kotlin Flow) পর্যবেক্ষণ করতে collectAsStateWithLifecycle ব্যবহার করুন। অ্যাপ ফোরগ্রাউন্ডে থাকাকালীন এটি আপনাকে লাইভ আপডেট দেয় এবং অ্যাপ ব্যাকগ্রাউন্ডে চলে গেলে অটোমেটিক সংগ্রহ বাতিল করে দেয়।
  • ভারী টাস্ক পজ করা এবং আবার চালু করা। অ্যাপ ব্যাকগ্রাউন্ডে থাকাকালীন ভারী ভিজ্যুয়াল আপডেট পজ করা এবং অ্যাপ ফোরগ্রাউন্ডে আসার পরে সেগুলি আবার চালু করার জন্য LifecycleResumeEffect ব্যবহার করুন।

নিরাপদে ON_STOP ইভেন্ট ম্যানেজ করা

Compose-কে এমনভাবে ডিজাইন করা হয়েছে যাতে ON_STOP ইভেন্ট নিরাপদে ম্যানেজ করা যায়।

  • স্টেট নিরাপদ: আপনি যেকোনও সময় MutableState (যেমন, uiState.value = ...-এর সাথে) আপডেট করতে পারবেন, এমনকি অ্যাপ ব্যাকগ্রাউন্ডে থাকলেও। পরিবর্তনগুলি রেন্ডার করার জন্য অ্যাপটি দৃশ্যমান না হওয়া পর্যন্ত Compose অপেক্ষা করে।
  • অটোমেটিক ক্লিনআপ: LifecycleStartEffect-এর মতো এফেক্টের মাধ্যমে, আপনার ক্লিনআপ ব্লক (onStopOrDispose) ঠিক তখনই রান করে যখন লাইফসাইকেল STOPPED-এ চলে যায়। অ্যাপ ব্যাকগ্রাউন্ডে থাকাকালীন এটি আপনাকে ভারী রিসোর্স (যেমন ক্যামেরা বা লোকেশন) হোল্ড করা থেকে আটকায়।

MutableState সম্পর্কে আরও তথ্যের জন্য, State ও Jetpack Compose দেখুন।

অতিরিক্ত রিসোর্স

লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্টের সাহায্যে লাইফসাইকেল ম্যানেজ করা সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত রিসোর্স দেখুন।

কন্টেন্ট দেখে