remember হল Jetpack Compose এর একটি ফাংশন যা আপনাকে পুনঃসংযোজনের মধ্যে একটি মান সংরক্ষণ করতে দেয়, প্রতিটি Composable ফাংশন পুনঃশুরুতে অবস্থা রিসেট হওয়া প্রতিরোধ করে। remember ছাড়া, ফাংশনের ভিতরে ঘোষিত সব ভেরিয়েবল প্রতিটি UI আপডেটে রিসেট হয়ে যেত, যা অবস্থাকে অস্থির এবং অকেজো করে তুলত। Google Android Developers, 2026 অনুসারে, remember এর সঠিক ব্যবহার ঘোষণামূলক UI তে সঠিক অবস্থা ব্যবস্থাপনার ভিত্তি।
মূল পয়েন্ট
remember হল androidx.compose.runtime প্যাকেজ থেকে একটি নির্মিত Jetpack Compose ফাংশন যা একটি অবজেক্ট তৈরি করে যা একটি Composable ফাংশনের ধারাবাহিক কলের মধ্যে তার মান সংরক্ষণ করে। প্রযুক্তিগতভাবে, remember স্লট নিয়ে কাজ করে — UI ট্রিতে প্রতিটি ফাংশন কল অবস্থানের জন্য বরাদ্দ বিশেষ মেমোরি কোষ। যতক্ষণ ফাংশন কম্পোজিশনে থাকে (if-শর্তের মাধ্যমে সরানো না হয়), remember প্রতিটি পুনঃসংযোজনে সংরক্ষিত মান ফিরিয়ে দেবে।
remember এর সিনট্যাক্স সহজ: কোঁকড়া বন্ধনীর ভিতরে প্রাথমিক মান গণনার ব্লক নির্দিষ্ট করা হয়। ব্লকটি শুধুমাত্র একবার নির্বাহিত হয় — ফাংশনের প্রথম কম্পোজিশনের সময়। সমস্ত পরবর্তী পুনঃসংযোজন ব্লকটি পুনরায় নির্বাহ না করেই পূর্বে সংরক্ষিত মান ফিরিয়ে দেয়। তবে, যদি একটি কী প্যারামিটার নির্দিষ্ট করা হয়, তবে কী পরিবর্তিত হলে ব্লকটি পুনরায় নির্বাহিত হয়, যা ইনপুট ডেটার উপর ভিত্তি করে মান পুনঃগণনা করতে দেয়।
remember Kotlin জাদু নয় — এটি একটি কী প্যারামিটার এবং গণনা ল্যাম্বডা সহ একটি সরল ফাংশন। এর অভ্যন্তরীণ বাস্তবায়ন স্লটে পড়তে এবং লিখতে Composer ব্যবহার করে। Kotlin কম্পাইলার, remember কল দেখে, কোড তৈরি করে যা বর্তমান CompositionContext এ অ্যাক্সেস করে এবং স্লটগুলি পরিচালনা করে। এর মানে হল remember শুধুমাত্র একটি Composable ফাংশনের ভিতরে বা কম্পোজিশন প্রসঙ্গের মধ্যে অন্য ফাংশনে কল করা যেতে পারে।
Jetpack Compose এ, remember এর তিনটি প্রধান প্রকার রয়েছে, প্রতিটির নিজস্ব উদ্দেশ্য রয়েছে। মৌলিক remember শুধুমাত্র বর্তমান প্রক্রিয়া মেমোরিতে মান সংরক্ষণ করে — স্ক্রিন ঘূর্ণনে (কনফিগ পরিবর্তন), Compose কম্পোজিশন পুনরায় তৈরি করে এবং সমস্ত remember মান রিসেট হয়। কনফিগারেশন পরিবর্তন এবং প্রক্রিয়া বন্ধের সময় ডেটা সংরক্ষণের জন্য rememberSaveable ব্যবহার করা হয়।
rememberSaveable SavedStateHandle বা Parcelable প্রক্রিয়ার মাধ্যমে মানকে Bundle এ ধারাবাহিক করে। এটি স্ক্রিন ঘূর্ণন, "ক্রিয়াকলাপ রাখবেন না" সেটিংস এবং এমনকি অস্থায়ী অ্যাপ ছোট করা থেকে বাঁচতে দেয়। তবে, rememberSaveable সংরক্ষণযোগ্য ডেটার প্রকারের উপর সীমাবদ্ধতা আরোপ করে: সেগুলি প্রিমিটিভ, Parcelable, Serializable হতে হবে অথবা Saver কনভার্টার সমর্থন করতে হবে।
derivedStateOf সংরক্ষণ প্রক্রিয়া নয় বরং একটি অপ্টিমাইজেশন। এটি এমন একটি State তৈরি করে যার মান অন্যান্য State অবজেক্ট থেকে গণনা করা হয়। derivedStateOf উৎস অবস্থার পরিবর্তনে সাড়া দেয় কিন্তু শুধুমাত্র তখনই মান পুনঃগণনা করে যখন গ্রাহক থাকে। যদি বর্তমান পুনঃসংযোজন derivedStateOf না পড়ে, তাহলে গণনা করা হয় না, যা ঘন ঘন কিন্তু অপ্রয়োজনীয় আপডেটে সম্পদ সাশ্রয় করে।
@Composable
fun RememberVariants() {
// 1. মৌলিক remember: কম্পোজিশন ছাড়া পর্যন্ত স্থায়ী হয়
val createdAt = remember { System.currentTimeMillis() }
// 2. rememberSaveable: স্ক্রিন ঘূর্ণন থেকে বেঁচে থাকে
var username by rememberSaveable { mutableStateOf("") }
// 3. derivedStateOf: শুধুমাত্র প্রয়োজন হলে গণনা করে
val isButtonVisible = remember {
derivedStateOf { username.length() > 3 }
}
Text("তৈরি: $createdAt")
TextField(value = username, onValueChange = { username = it })
if (isButtonVisible.value) {
Text("বাটন দেখানো হবে")
}
}
remember এবং rememberSaveable এর মধ্যে পছন্দ নির্ভর করে কনফিগারেশন পরিবর্তনের সময় ডেটা সংরক্ষণ করা কতটা গুরুত্বপূর্ণ তার উপর। অস্থায়ী অবস্থার জন্য যা ঘূর্ণনে হারানো গুরুত্বপূর্ণ নয় (অ্যানিমেশন, বর্তমান স্ক্রোল অবস্থান, ফোকাস অবস্থা) — সাধারণ remember যথেষ্ট। গুরুত্বপূর্ণ ডেটার জন্য (ফর্মে টেক্সট, নির্বাচিত আইটেম, চেকবক্স) — rememberSaveable ব্যবহার করুন।
কর্মক্ষমতা: rememberSaveable সাধারণ remember এর চেয়ে ধীর কারণ এটিকে Bundle এ ধারাবাহিক করতে হয়। rememberSaveable শুধুমাত্র সেই ডেটার জন্য ব্যবহার করুন যা সত্যিই Activity পুনর্নির্মাণ থেকে বাঁচতে হবে। বাকি সবকিছুর জন্য — সরল remember। rememberSaveable এর অত্যধিক ব্যবহার স্ক্রিন ঘূর্ণন এবং অ্যাপের মধ্যে স্যুইচ করার সময় মন্থরতা সৃষ্টি করে।
যদি আপনি Parcelable বা Serializable সমর্থন করে না এমন ক্লাস নিয়ে কাজ করেন, তাহলে Saver ব্যবহার করুন — একটি কনভার্টার যা সংজ্ঞায়িত করে কিভাবে অবজেক্ট সংরক্ষণ এবং পুনরুদ্ধার করতে হয়। Saver ল্যাম্বডার একটি জোড়া দ্বারা বর্ণিত: save (অবজেক্টকে সংরক্ষণযোগ্য প্রকারে রূপান্তর করে) এবং restore (সংরক্ষিত ডেটা থেকে অবজেক্ট পুনরুদ্ধার করে)। mutableStateListOf এবং mutableStateMapOf এর জন্য একটি মানক Saver ইতিমধ্যে বাস্তবায়িত রয়েছে।
| বৈশিষ্ট্য | remember | rememberSaveable |
|---|---|---|
| পুনঃসংযোজনে সংরক্ষণ | হ্যাঁ | হ্যাঁ |
| ঘূর্ণনে সংরক্ষণ | না | হ্যাঁ |
| প্রক্রিয়া বন্ধে সংরক্ষণ | না | হ্যাঁ |
| প্রকারের প্রয়োজনীয়তা | যেকোনো | Parcelable, Serializable, Saver |
| কর্মক্ষমতা | উচ্চ | মধ্যম |
একটি সাধারণ দৃশ্যকল্প বিবেচনা করুন — একটি প্রোফাইল সম্পাদনা স্ক্রিন যেখানে remember বিভিন্ন উদ্দেশ্যে ব্যবহার করা হয়: ফর্ম ফিল্ডের অবস্থা সংরক্ষণ, উদ্ভূত মান গণনা এবং গণনাগতভাবে ব্যয়বহুল অপারেশন ক্যাশ করা।
data class ProfileUiState(
val name: String = "",
val bio: String = "",
val isSaving: Boolean = false
)
@Composable
fun ProfileEditor() {
var state by rememberSaveable { mutableStateOf(ProfileUiState()) }
val isValid = remember {
derivedStateOf { state.name.isNotBlank() && state.bio.length() <= 500 }
}
val bioWarning = remember(state.bio) {
if (state.bio.length() > 400) {
"${500 - state.bio.length} chars left"
} else null
}
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = state.name,
onValueChange = { state = state.copy(name = it) },
label = { Text("নাম") }
)
OutlinedTextField(
value = state.bio,
onValueChange = { state = state.copy(bio = it) },
label = { Text("সম্পর্কে") }
)
bioWarning?.let { Text(it, color = MaterialTheme.colorScheme.error) }
Button(onClick = { /* save */ },
enabled = isValid.value) {
Text("সংরক্ষণ")
}
}
}
উদাহরণে, অবস্থা rememberSaveable এর মাধ্যমে সংরক্ষিত হয় — স্ক্রিন ঘূর্ণনে টেক্সট হারিয়ে যাবে না। isValid derivedStateOf এর মাধ্যমে গণনা করা হয়, যা পুনঃসংযোজনের সময় অপ্রয়োজনীয় গণনা প্রতিরোধ করে। bioWarning bio কী সহ remember ব্যবহার করে — এটি একটি ব্যয়বহুল গণনা (ঐচ্ছিক, প্রদর্শনের জন্য) যা শুধুমাত্র bio পরিবর্তিত হলে পুনঃগণনা করে, প্রতিটি পুনঃসংযোজনে নয়।
উদ্ভূত অবস্থা হল মান যা অন্যান্য State অবজেক্ট থেকে গণনা করা হয়। প্রতিটি পুনঃসংযোজনে সেগুলি গণনা করে এবং অভিন্ন ফলাফলে CPU নষ্ট করার পরিবর্তে, remember derivedStateOf সহ শুধুমাত্র তখনই মান গণনা করে যখন উৎস পরিবর্তিত হয়। এটি বিশেষ করে ফিল্টারিং, সর্টিং এবং ডেটা একত্রীকরণের জন্য উপযোগী।
কী সহ remember (remember(key) { calculation }) আরেকটি অপ্টিমাইজেশন প্রক্রিয়া। যদি শেষ পুনঃসংযোজনের পর থেকে কী পরিবর্তিত না হয়, তাহলে গণনা ব্লক নির্বাহিত হয় না এবং ক্যাশ করা মান ফিরিয়ে দেওয়া হয়। এটি এমন অবজেক্ট ক্যাশ করার জন্য সুবিধাজনক যাদের তৈরি ব্যয়বহুল: তারিখ ফরম্যাটিং, JSON পার্সিং, বড় অপরিবর্তনীয় সংগ্রহ তৈরি করা।
@Composable
fun SearchResults(allItems: List<Item>, query: String) {
// derivedStateOf: ফিল্টার শুধুমাত্র ইনপুট পরিবর্তিত হলে পুনঃগণনা করে
val filtered = remember {
derivedStateOf {
allItems.filter { it.title.contains(query, true) }
}
}
// কী সহ remember: ফরম্যাট করা পরিসংখ্যান শুধুমাত্র কোয়েরি পরিবর্তিত হলে পুনঃগণনা করে
val statsText = remember(query) {
"Results for query \"$query\": ${filtered.value.size}"
}
Text(statsText)
LazyColumn {
items(filtered.value, key = { it.id }) { item ->
Text(item.title)
}
}
}
filtered হল একটি derivedStateOf যা allItems বা query পরিবর্তিত হলে স্বয়ংক্রিয়ভাবে পুনঃগণনা করে। statsText remember(query) ব্যবহার করে — ব্যয়বহুল স্ট্রিং ফরম্যাটিং শুধুমাত্র তখনই করা হয় যখন অনুসন্ধান কোয়েরি পরিবর্তিত হয়। derivedStateOf এবং কী সহ remember এর সংমিশ্রণ সর্বোচ্চ কর্মক্ষমতা দেয়: উদ্ভূত অবস্থা শুধুমাত্র প্রয়োজন হলে গণনা করা হয় এবং জটিল অবজেক্ট কী পরিবর্তন না হওয়া পর্যন্ত ক্যাশ করা হয়।
সচরাচর জিজ্ঞাসিত প্রশ্ন
না, remember হল compose.runtime প্যাকেজের একটি ফাংশন যার CompositionContext প্রয়োজন। এটি শুধুমাত্র @Composable ফাংশনের ভিতরে অথবা Composable থেকে কল করা অন্য ফাংশনের ভিতরে কল করা যেতে পারে। কম্পোজিশনের বাইরে ডেটা সংরক্ষণের জন্য, ViewModel ব্যবহার করুন।
কী ছাড়া, remember গণনা ব্লকটি শুধুমাত্র একবার নির্বাহ করে — প্রথম কম্পোজিশনের সময়। সমস্ত পরবর্তী পুনঃসংযোজন সংরক্ষিত মান ফিরিয়ে দেয়। যদি ডেটা পরিবর্তিত হলে মান পুনঃগণনা করার প্রয়োজন হয়, তাহলে সেগুলিকে কী হিসাবে নির্দিষ্ট করতে ভুলবেন না: remember(data) { compute(data) }।
remember সরাসরি রিসেট করার কোন উপায় নেই। একমাত্র উপায় হল ফাংশনটিকে কম্পোজিশন থেকে সরানো (উদাহরণস্বরূপ, if-শর্ত দিয়ে লুকানো) এবং তারপর এটি আবার দেখানো। পুনঃপ্রবেশে, remember ব্লকটি আবার নির্বাহিত হয়, একটি নতুন প্রাথমিক মান তৈরি করে।
remember একটি Composable ফাংশন স্লটে অবস্থা সংরক্ষণ করে এবং যতক্ষণ ফাংশন কম্পোজিশনে থাকে ততক্ষণ বেঁচে থাকে। ViewModel ততক্ষণ বেঁচে থাকে যতক্ষণ স্ক্রিনের জীবনচক্র থাকে। ViewModel ঘূর্ণনে সংরক্ষিত হয় এবং ব্যবসায়িক যুক্তির জন্য ব্যবহৃত হয়। remember স্থানীয় UI অবস্থার জন্য যা একটি একক ফাংশনের বাইরে প্রয়োজন হয় না।
হ্যাঁ, remember @Preview Composable ফাংশনে সঠিকভাবে কাজ করে কারণ Preview একটি সম্পূর্ণ CompositionContext তৈরি করে। তবে, rememberSaveable Preview এ সঠিকভাবে কাজ নাও করতে পারে কারণ পূর্বরূপ পরিবেশে SavedStateHandle অনুপস্থিত থাকতে পারে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন