কম্পোজ এর পার্শ্বপ্রতিক্রিয়া

একটি পার্শ্ব-প্রতিক্রিয়া হল অ্যাপের অবস্থার পরিবর্তন যা একটি সংমিশ্রণযোগ্য ফাংশনের সুযোগের বাইরে ঘটে। কম্পোজেবলের জীবনচক্র এবং বৈশিষ্ট্যের কারণে যেমন অপ্রত্যাশিত পুনর্গঠন, বিভিন্ন ক্রমে কম্পোজেবলের পুনর্গঠন কার্যকর করা, বা বাতিল করা যেতে পারে এমন পুনর্গঠন, কম্পোজেবলগুলি আদর্শভাবে পার্শ্ব-প্রতিক্রিয়া মুক্ত হওয়া উচিত

যাইহোক, কখনও কখনও পার্শ্ব-প্রতিক্রিয়া প্রয়োজন হয়, উদাহরণস্বরূপ, একটি স্ন্যাকবার দেখানো বা একটি নির্দিষ্ট অবস্থার শর্তে অন্য স্ক্রিনে নেভিগেট করার মতো এক-অফ ইভেন্ট ট্রিগার করতে। এই ক্রিয়াগুলি একটি নিয়ন্ত্রিত পরিবেশ থেকে বলা উচিত যা কম্পোজেবলের জীবনচক্র সম্পর্কে সচেতন। এই পৃষ্ঠায়, আপনি বিভিন্ন পার্শ্ব-প্রতিক্রিয়া APIs Jetpack Compose অফার সম্পর্কে শিখবেন।

রাষ্ট্র এবং প্রভাব ব্যবহার ক্ষেত্রে

থিংকিং ইন কম্পোজ ডকুমেন্টেশনে কভার করা হয়েছে, কম্পোজেবলগুলি পার্শ্ব-প্রতিক্রিয়ামুক্ত হওয়া উচিত। যখন আপনাকে অ্যাপের অবস্থাতে পরিবর্তন করতে হবে (যেমন ম্যানেজিং স্টেট ডকুমেন্টেশন ডক-এ বর্ণনা করা হয়েছে), তখন আপনার ইফেক্ট API ব্যবহার করা উচিত যাতে সেই পার্শ্বপ্রতিক্রিয়াগুলি অনুমানযোগ্য পদ্ধতিতে কার্যকর হয়

কম্পোজে বিভিন্ন সম্ভাবনার প্রভাব খোলার কারণে, সেগুলি সহজেই অতিরিক্ত ব্যবহার করা যেতে পারে। নিশ্চিত করুন যে আপনি এগুলিতে যে কাজটি করেন তা UI সম্পর্কিত এবং ম্যানেজিং স্টেট ডকুমেন্টেশনে ব্যাখ্যা অনুসারে একমুখী ডেটা প্রবাহকে ভঙ্গ করে না।

LaunchedEffect : একটি কম্পোজেবলের সুযোগে সাসপেন্ড ফাংশন চালান

একটি কম্পোজেবলের জীবনকাল ধরে কাজ করতে এবং সাসপেন্ড ফাংশন কল করার ক্ষমতা থাকতে, LaunchedEffect কম্পোজেবল ব্যবহার করুন। যখন LaunchedEffect কম্পোজিশনে প্রবেশ করে, তখন এটি প্যারামিটার হিসাবে পাস করা কোড ব্লকের সাথে একটি করুটিন চালু করে। LaunchedEffect রচনাটি ছেড়ে দিলে coroutine বাতিল করা হবে৷ যদি LaunchedEffect বিভিন্ন কী দিয়ে পুনরায় কম্পোজ করা হয় (নীচের রিস্টার্টিং ইফেক্টস বিভাগটি দেখুন), বিদ্যমান coroutine বাতিল করা হবে এবং নতুন coroutine-এ নতুন সাসপেন্ড ফাংশন চালু করা হবে।

উদাহরণস্বরূপ, এখানে একটি অ্যানিমেশন রয়েছে যা একটি কনফিগারযোগ্য বিলম্বের সাথে আলফা মানকে স্পন্দিত করে:

// Allow the pulse rate to be configured, so it can be sped up if the user is running
// out of time
var pulseRateMs by remember { mutableStateOf(3000L) }
val alpha = remember { Animatable(1f) }
LaunchedEffect(pulseRateMs) { // Restart the effect when the pulse rate changes
    while (isActive) {
        delay(pulseRateMs) // Pulse the alpha every pulseRateMs to alert the user
        alpha.animateTo(0f)
        alpha.animateTo(1f)
    }
}

উপরের কোডে, অ্যানিমেশনটি নির্দিষ্ট সময়ের জন্য অপেক্ষা করতে সাসপেন্ডিং ফাংশন delay ব্যবহার করে। তারপর, এটি ক্রমানুসারে animateTo ব্যবহার করে আলফাকে শূন্য করে এবং আবার ফিরে আসে। এটি কম্পোজেবলের জীবনের জন্য পুনরাবৃত্তি হবে।

rememberCoroutineScope : কম্পোজেবলের বাইরে কোরোটিন চালু করার জন্য একটি রচনা-সচেতন সুযোগ পান

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

rememberCoroutineScope হল একটি সংমিশ্রণযোগ্য ফাংশন যা কম্পোজিশনের বিন্দুতে আবদ্ধ একটি CoroutineScope ফেরত দেয় যেখানে এটি বলা হয়। কলটি রচনাটি ছেড়ে গেলে সুযোগটি বাতিল হয়ে যাবে৷

পূর্ববর্তী উদাহরণ অনুসরণ করে, ব্যবহারকারী যখন একটি Button ট্যাপ করে তখন আপনি একটি Snackbar দেখানোর জন্য এই কোডটি ব্যবহার করতে পারেন:

@Composable
fun MoviesScreen(snackbarHostState: SnackbarHostState) {

    // Creates a CoroutineScope bound to the MoviesScreen's lifecycle
    val scope = rememberCoroutineScope()

    Scaffold(
        snackbarHost = {
            SnackbarHost(hostState = snackbarHostState)
        }
    ) { contentPadding ->
        Column(Modifier.padding(contentPadding)) {
            Button(
                onClick = {
                    // Create a new coroutine in the event handler to show a snackbar
                    scope.launch {
                        snackbarHostState.showSnackbar("Something happened!")
                    }
                }
            ) {
                Text("Press me")
            }
        }
    }
}

rememberUpdatedState : একটি প্রভাবে একটি মান উল্লেখ করুন যা মান পরিবর্তন হলে পুনরায় আরম্ভ করা উচিত নয়

LaunchedEffect পুনঃসূচনা হয় যখন মূল পরামিতিগুলির একটি পরিবর্তন হয়। যাইহোক, কিছু পরিস্থিতিতে আপনি আপনার প্রভাবের একটি মান ক্যাপচার করতে চাইতে পারেন যেটি যদি পরিবর্তন হয়, আপনি প্রভাবটি পুনরায় চালু করতে চান না। এটি করার জন্য, এই মানটির একটি রেফারেন্স তৈরি করতে rememberUpdatedState ব্যবহার করতে হবে যা ক্যাপচার এবং আপডেট করা যেতে পারে। এই পদ্ধতিটি এমন প্রভাবগুলির জন্য সহায়ক যেগুলিতে দীর্ঘস্থায়ী ক্রিয়াকলাপ রয়েছে যা পুনরায় তৈরি এবং পুনরায় চালু করা ব্যয়বহুল বা নিষিদ্ধ হতে পারে।

উদাহরণস্বরূপ, ধরুন আপনার অ্যাপে একটি LandingScreen আছে যা কিছু সময় পরে অদৃশ্য হয়ে যায়। এমনকি যদি LandingScreen পুনর্গঠিত হয়, তবে প্রভাব যা কিছু সময়ের জন্য অপেক্ষা করে এবং জানিয়ে দেয় যে সময় অতিবাহিত করা পুনরায় চালু করা উচিত নয়:

@Composable
fun LandingScreen(onTimeout: () -> Unit) {

    // This will always refer to the latest onTimeout function that
    // LandingScreen was recomposed with
    val currentOnTimeout by rememberUpdatedState(onTimeout)

    // Create an effect that matches the lifecycle of LandingScreen.
    // If LandingScreen recomposes, the delay shouldn't start again.
    LaunchedEffect(true) {
        delay(SplashWaitTimeMillis)
        currentOnTimeout()
    }

    /* Landing screen content */
}

কল সাইটের লাইফসাইকেলের সাথে মেলে এমন একটি প্রভাব তৈরি করতে, Unit বা true মতো একটি কখনও পরিবর্তন না হওয়া ধ্রুবককে একটি প্যারামিটার হিসাবে পাস করা হয়। উপরের কোডে, LaunchedEffect(true) ব্যবহার করা হয়েছে। onTimeout ল্যাম্বডায় সর্বদা লেটেস্ট মান রয়েছে যা LandingScreen সাথে পুনর্গঠিত হয়েছে তা নিশ্চিত করতে, onTimeout rememberUpdatedState ফাংশন দিয়ে মোড়ানো প্রয়োজন। কোডে প্রত্যাবর্তিত State , currentOnTimeout , প্রভাবে ব্যবহার করা উচিত।

DisposableEffect : এমন প্রভাব যা পরিষ্কারের প্রয়োজন

পার্শ্ব প্রতিক্রিয়াগুলির জন্য যা কী পরিবর্তনের পরে পরিষ্কার করা দরকার বা যদি কম্পোজেবল কম্পোজিশন ছেড়ে যায়, DisposableEffect ব্যবহার করুন। যদি DisposableEffect কীগুলি পরিবর্তন হয়, তাহলে কম্পোজেবলকে তার বর্তমান প্রভাবটি নিষ্পত্তি করতে হবে (পরিষ্কার করতে হবে) এবং প্রভাবটিকে আবার কল করে পুনরায় সেট করতে হবে।

একটি উদাহরণ হিসাবে, আপনি একটি LifecycleObserver ব্যবহার করে Lifecycle ইভেন্টের উপর ভিত্তি করে বিশ্লেষণ ইভেন্ট পাঠাতে চাইতে পারেন। কম্পোজে সেই ইভেন্টগুলি শোনার জন্য, প্রয়োজনে পর্যবেক্ষককে নিবন্ধন এবং নিবন্ধনমুক্ত করতে একটি DisposableEffect ব্যবহার করুন।

@Composable
fun HomeScreen(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onStart: () -> Unit, // Send the 'started' analytics event
    onStop: () -> Unit // Send the 'stopped' analytics event
) {
    // Safely update the current lambdas when a new one is provided
    val currentOnStart by rememberUpdatedState(onStart)
    val currentOnStop by rememberUpdatedState(onStop)

    // If `lifecycleOwner` changes, dispose and reset the effect
    DisposableEffect(lifecycleOwner) {
        // Create an observer that triggers our remembered callbacks
        // for sending analytics events
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_START) {
                currentOnStart()
            } else if (event == Lifecycle.Event.ON_STOP) {
                currentOnStop()
            }
        }

        // Add the observer to the lifecycle
        lifecycleOwner.lifecycle.addObserver(observer)

        // When the effect leaves the Composition, remove the observer
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    /* Home screen content */
}

উপরের কোডে, প্রভাব observer lifecycleOwner সাথে যুক্ত করবে। lifecycleOwner পরিবর্তন হলে, প্রভাবটি নিষ্পত্তি করা হয় এবং নতুন lifecycleOwner সাথে পুনরায় চালু করা হয়।

একটি DisposableEffect অবশ্যই তার ব্লকের কোডে চূড়ান্ত বিবৃতি হিসাবে একটি onDispose ক্লজ অন্তর্ভুক্ত করতে হবে। অন্যথায়, IDE একটি বিল্ড-টাইম ত্রুটি প্রদর্শন করে।

SideEffect : নন-কম্পোজ কোডে কম্পোজ স্টেট প্রকাশ করুন

কম্পোজ দ্বারা পরিচালিত নয় এমন বস্তুর সাথে কম্পোজ স্টেট শেয়ার করতে, SideEffect কম্পোজেবল ব্যবহার করুন। একটি SideEffect ব্যবহার নিশ্চিত করে যে প্রভাব প্রতিটি সফল পুনর্গঠনের পরে কার্যকর হয়। অন্যদিকে, একটি সফল পুনর্গঠনের গ্যারান্টি দেওয়ার আগে একটি প্রভাব সম্পাদন করা ভুল, এটি একটি কম্পোজেবলে সরাসরি প্রভাব লেখার ক্ষেত্রে।

উদাহরণ স্বরূপ, আপনার অ্যানালিটিক্স লাইব্রেরি আপনাকে পরবর্তী সমস্ত অ্যানালিটিক্স ইভেন্টগুলিতে কাস্টম মেটাডেটা (এই উদাহরণে "ব্যবহারকারীর বৈশিষ্ট্য") সংযুক্ত করে আপনার ব্যবহারকারীর জনসংখ্যাকে ভাগ করার অনুমতি দিতে পারে। আপনার বিশ্লেষণ লাইব্রেরিতে বর্তমান ব্যবহারকারীর ব্যবহারকারীর প্রকারের সাথে যোগাযোগ করতে, এর মান আপডেট করতে SideEffect ব্যবহার করুন।

@Composable
fun rememberFirebaseAnalytics(user: User): FirebaseAnalytics {
    val analytics: FirebaseAnalytics = remember {
        FirebaseAnalytics()
    }

    // On every successful composition, update FirebaseAnalytics with
    // the userType from the current User, ensuring that future analytics
    // events have this metadata attached
    SideEffect {
        analytics.setUserProperty("userType", user.userType)
    }
    return analytics
}

produceState : নন-কম্পোজ স্টেটকে কম্পোজ স্টেটে রূপান্তর করুন

produceState কম্পোজিশনের স্কোপযুক্ত একটি কোরোটিন চালু করে যা মানগুলিকে একটি প্রত্যাবর্তিত State ঠেলে দিতে পারে। নন-কম্পোজ স্টেটকে কম্পোজ স্টেটে রূপান্তর করতে এটি ব্যবহার করুন, উদাহরণস্বরূপ কম্পোজিশনে Flow , LiveData বা RxJava এর মতো বাহ্যিক সাবস্ক্রিপশন-চালিত অবস্থা আনা।

প্রোডাক্ট produceState যখন কম্পোজিশনে প্রবেশ করে তখন প্রযোজক চালু হয়, এবং কম্পোজিশন থেকে বের হয়ে গেলে বাতিল করা হবে। প্রত্যাবর্তিত State সংঘটিত হয়; একই মান সেট করা একটি পুনর্গঠন ট্রিগার করবে না।

যদিও produceState একটি করুটিন তৈরি করে, এটি ডেটার অ-সাসপেন্ডিং উত্স পর্যবেক্ষণ করতেও ব্যবহার করা যেতে পারে। সেই উৎসের সাবস্ক্রিপশন অপসারণ করতে, awaitDispose ফাংশনটি ব্যবহার করুন।

নিম্নলিখিত উদাহরণ দেখায় কিভাবে produceState ব্যবহার করে নেটওয়ার্ক থেকে একটি ইমেজ লোড করতে হয়। loadNetworkImage কম্পোজেবল ফাংশন একটি State প্রদান করে যা অন্যান্য কম্পোজেবলে ব্যবহার করা যেতে পারে।

@Composable
fun loadNetworkImage(
    url: String,
    imageRepository: ImageRepository = ImageRepository()
): State<Result<Image>> {

    // Creates a State<T> with Result.Loading as initial value
    // If either `url` or `imageRepository` changes, the running producer
    // will cancel and will be re-launched with the new inputs.
    return produceState<Result<Image>>(initialValue = Result.Loading, url, imageRepository) {

        // In a coroutine, can make suspend calls
        val image = imageRepository.load(url)

        // Update State with either an Error or Success result.
        // This will trigger a recomposition where this State is read
        value = if (image == null) {
            Result.Error
        } else {
            Result.Success(image)
        }
    }
}

derivedStateOf : এক বা একাধিক স্টেট অবজেক্টকে অন্য স্টেটে রূপান্তর করুন

কম্পোজে, প্রতিবার যখন একটি পর্যবেক্ষণ করা স্টেট অবজেক্ট বা কম্পোজেবল ইনপুট পরিবর্তন হয় তখন পুনর্গঠন ঘটে। একটি স্টেট অবজেক্ট বা ইনপুট UI কে প্রকৃতপক্ষে আপডেট করার প্রয়োজনের চেয়ে অনেক বেশি পরিবর্তিত হতে পারে, যা অপ্রয়োজনীয় পুনর্গঠনের দিকে পরিচালিত করে।

আপনার derivedStateOf ফাংশনটি ব্যবহার করা উচিত যখন একটি কম্পোজেবলের ইনপুটগুলি আপনার পুনরায় কম্পোজ করার প্রয়োজনের চেয়ে বেশি বার পরিবর্তিত হয়। এটি প্রায়শই ঘটে যখন কিছু ঘন ঘন পরিবর্তন হয়, যেমন একটি স্ক্রোল অবস্থান, কিন্তু কম্পোজেবল শুধুমাত্র একটি নির্দিষ্ট থ্রেশহোল্ড অতিক্রম করার পরে এটিতে প্রতিক্রিয়া দেখাতে হবে। derivedStateOf একটি নতুন কম্পোজ স্টেট অবজেক্ট তৈরি করে যা আপনি লক্ষ্য করতে পারেন যে আপনার যতটুকু প্রয়োজন ততটুকুই আপডেট হয়। এইভাবে, এটি Kotlin Flows distinctUntilChanged() অপারেটরের অনুরূপভাবে কাজ করে।

সঠিক ব্যবহার

নিম্নলিখিত স্নিপেট derivedStateOf এর জন্য উপযুক্ত ব্যবহারের ক্ষেত্রে দেখায়:

@Composable
// When the messages parameter changes, the MessageList
// composable recomposes. derivedStateOf does not
// affect this recomposition.
fun MessageList(messages: List<Message>) {
    Box {
        val listState = rememberLazyListState()

        LazyColumn(state = listState) {
            // ...
        }

        // Show the button if the first visible item is past
        // the first item. We use a remembered derived state to
        // minimize unnecessary compositions
        val showButton by remember {
            derivedStateOf {
                listState.firstVisibleItemIndex > 0
            }
        }

        AnimatedVisibility(visible = showButton) {
            ScrollToTopButton()
        }
    }
}

এই স্নিপেটে, firstVisibleItemIndex যে কোনো সময় প্রথম দৃশ্যমান আইটেম পরিবর্তন হয়। আপনি স্ক্রোল করার সাথে সাথে মানটি 0 , 1 , 2 , 3 , 4 , 5 , ইত্যাদি হয়ে যায়৷ যাইহোক, যদি মানটি 0 -এর বেশি হয় তবেই পুনর্গঠন ঘটতে হবে৷ আপডেট ফ্রিকোয়েন্সিতে এই অমিলের অর্থ হল এটি derivedStateOf এর জন্য একটি ভাল ব্যবহারের ক্ষেত্রে।

ভুল ব্যবহার

একটি সাধারণ ভুল হল অনুমান করা যে, আপনি যখন দুটি কম্পোজ স্টেট অবজেক্ট একত্রিত করেন, তখন আপনার derivedStateOf ব্যবহার করা উচিত কারণ আপনি "ডিরিভিং স্টেট"। যাইহোক, এটি সম্পূর্ণরূপে ওভারহেড এবং প্রয়োজনীয় নয়, যেমনটি নিম্নলিখিত স্নিপেটে দেখানো হয়েছে:

// DO NOT USE. Incorrect usage of derivedStateOf.
var firstName by remember { mutableStateOf("") }
var lastName by remember { mutableStateOf("") }

val fullNameBad by remember { derivedStateOf { "$firstName $lastName" } } // This is bad!!!
val fullNameCorrect = "$firstName $lastName" // This is correct

এই স্নিপেটে, fullName firstName এবং lastName যতবার আপডেট করতে হবে। অতএব, কোন অতিরিক্ত পুনর্গঠন ঘটছে না, এবং derivedStateOf ব্যবহার করার প্রয়োজন নেই।

snapshotFlow : রচনার অবস্থাকে ফ্লোতে রূপান্তর করুন

State<T> অবজেক্টকে ঠান্ডা প্রবাহে রূপান্তর করতে snapshotFlow ব্যবহার করুন। snapshotFlow সংগ্রহ করা হলে তার ব্লক চালায় এবং এতে পড়া State অবজেক্টের ফলাফল নির্গত করে। যখন State অবজেক্টগুলির একটি snapshotFlow ব্লকের ভিতরে পড়ে, তখন ফ্লো তার সংগ্রাহকের কাছে নতুন মান নির্গত করবে যদি নতুন মানটি আগের নির্গত মানের সমান না হয় (এই আচরণটি Flow.distinctUntilChanged এর মতো)।

নিম্নলিখিত উদাহরণটি একটি পার্শ্ব প্রতিক্রিয়া দেখায় যা রেকর্ড করে যখন ব্যবহারকারী একটি তালিকার প্রথম আইটেমটিকে বিশ্লেষণে স্ক্রোল করে:

val listState = rememberLazyListState()

LazyColumn(state = listState) {
    // ...
}

LaunchedEffect(listState) {
    snapshotFlow { listState.firstVisibleItemIndex }
        .map { index -> index > 0 }
        .distinctUntilChanged()
        .filter { it == true }
        .collect {
            MyAnalyticsService.sendScrolledPastFirstItemEvent()
        }
}

উপরের কোডে, listState.firstVisibleItemIndex একটি ফ্লোতে রূপান্তরিত হয়েছে যা ফ্লো-এর অপারেটরদের ক্ষমতা থেকে উপকৃত হতে পারে।

প্রভাব পুনরায় চালু হচ্ছে

কম্পোজের কিছু ইফেক্ট, যেমন LaunchedEffect , produceState , বা DisposableEffect , একটি পরিবর্তনশীল সংখ্যক আর্গুমেন্ট, কী, যা চলমান প্রভাব বাতিল করতে এবং নতুন কী দিয়ে একটি নতুন শুরু করতে ব্যবহৃত হয়।

এই APIগুলির জন্য সাধারণ ফর্ম হল:

EffectName(restartIfThisKeyChanges, orThisKey, orThisKey, ...) { block }

এই আচরণের সূক্ষ্মতার কারণে, সমস্যাগুলি ঘটতে পারে যদি প্রভাবটি পুনরায় চালু করতে ব্যবহৃত পরামিতিগুলি সঠিক না হয়:

  • ইফেক্টের চেয়ে কম রিস্টার্ট করলে আপনার অ্যাপে বাগ হতে পারে।
  • প্রভাবগুলি পুনঃসূচনা করা উচিত তার চেয়ে বেশি অকার্যকর হতে পারে।

একটি নিয়ম হিসাবে, কোডের ইফেক্ট ব্লকে ব্যবহৃত পরিবর্তনযোগ্য এবং অপরিবর্তনীয় ভেরিয়েবলগুলিকে ইফেক্ট কম্পোজেবলের প্যারামিটার হিসাবে যুক্ত করা উচিত। এগুলি ছাড়াও, প্রভাব পুনরায় চালু করার জন্য আরও পরামিতি যোগ করা যেতে পারে। যদি একটি ভেরিয়েবলের পরিবর্তনের ফলে প্রভাবটি পুনরায় চালু না হয়, তাহলে ভেরিয়েবলটি স্মরণে মুড়িয়ে দেওয়া উচিত rememberUpdatedState । যদি ভেরিয়েবলটি কখনই পরিবর্তিত না হয় কারণ এটি কোন কী ছাড়াই remember রাখা হয়, তাহলে আপনাকে প্রভাবের কী হিসাবে ভেরিয়েবলটি পাস করতে হবে না।

উপরে দেখানো DisposableEffect কোডে, প্রভাবটি একটি প্যারামিটার হিসাবে lifecycleOwner তার ব্লকে ব্যবহৃত হয়, কারণ তাদের যে কোনও পরিবর্তন প্রভাবকে পুনরায় চালু করতে হবে।

@Composable
fun HomeScreen(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onStart: () -> Unit, // Send the 'started' analytics event
    onStop: () -> Unit // Send the 'stopped' analytics event
) {
    // These values never change in Composition
    val currentOnStart by rememberUpdatedState(onStart)
    val currentOnStop by rememberUpdatedState(onStop)

    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            /* ... */
        }

        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

currentOnStart এবং currentOnStop DisposableEffect কী হিসাবে প্রয়োজন নেই, কারণ rememberUpdatedState ব্যবহারের কারণে তাদের মান কখনই কম্পোজিশনে পরিবর্তন হয় না। আপনি যদি lifecycleOwner প্যারামিটার হিসাবে পাস না করেন এবং এটি পরিবর্তিত হয়, HomeScreen পুনরায় সংকলিত হয়, কিন্তু DisposableEffect নিষ্পত্তি করা হয় না এবং পুনরায় চালু হয়। এটি সমস্যার সৃষ্টি করে কারণ সেই বিন্দু থেকে ভুল lifecycleOwner ব্যবহার করা হয়।

কী হিসাবে ধ্রুবক

আপনি কল সাইটের লাইফ সাইকেল অনুসরণ করতে ইফেক্ট কী হিসাবে true মতো একটি ধ্রুবক ব্যবহার করতে পারেন। এটির জন্য বৈধ ব্যবহারের ক্ষেত্রে রয়েছে, যেমন উপরে দেখানো LaunchedEffect উদাহরণ। যাইহোক, এটি করার আগে, দুবার চিন্তা করুন এবং নিশ্চিত করুন যে এটি আপনার প্রয়োজন।

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}