MutableState Jetpack Compose میں ایک انٹرفیس ہے جو ایک قابل تبدیل قابل مشاہدہ قدر کے لیے کنٹینر کی نمائندگی کرتا ہے۔ یہ Compose کے ری اکٹو سسٹم کی بنیاد ہے: جب بھی MutableState کی قدر setter کے ذریعے بدلتی ہے، Compose Runtime تمام پڑھنے والے اجزاء کو مطلع کرتا ہے اور دوبارہ ترتیب شروع کرتا ہے۔ Google Android Developers, 2026 کے مطابق، ایک اعلانی UI میں حالت کے ساتھ صحیح طریقے سے کام کرنے کے لیے MutableState کو سمجھنا لازمی ہے۔
اهم نکات
MutableState androidx.compose.runtime پیکیج کا ایک انٹرفیس ہے جو ایک پراپرٹی کا اعلان کرتا ہے: override var value: T۔ getter موجودہ قدر واپس کرتا ہے، setter ایک نئی قدر لکھتا ہے اور Compose Runtime کو تبدیلی کی طلاع دیتا ہے۔ یہ انٹرفیس State<T> سے وراثت پاتا ہے، جہاں value صرف پڑھنے کے لیے ہے۔ یہ دو سطحی آرکی ٹیکچر رسائی کو علاحدہ کرنے کی اجازت دیتا ہے: ایک جزو جو صرف قدر پڑھنا چاہتا ہے وہ State<T> وصول کرتا ہے، جبکہ مالک جزو MutableState<T> وصول کرتا ہے۔
MutableState کا طرحی نفاذ انڈرونی کلاس SnapshotMutableStateImpl ہے، جو تبدیلیوں کو ٹریک کرنے کے لیے snapshot میکینزم استعمال کرتا ہے۔ جب value کا setter بلایا جاتا ہے، موجودہ snapshot لیکھنی کو ریکارڈ کرتا ہے اور سب رجسٹر شدہ ObservedScope کو غیر معتبر کے طور پر نشان دے دیتا ہے۔ یہ دائرے (عموماً Composable فنکشنز) اگلے فریم پر دوبارہ ترتیب دیے جائیں گے۔ Lock-free snapshot آرکی ٹیکچر کی وجہ سے پورا عمل مطابقتی اور بغیر قفل کے ہوتا ہے۔
State vs MutableState: State ایک صرف پڑھنے کا انٹرفیس ہے جو عام اجزاء API کے لیے استعمال ہوتا ہے۔ جب آپ ایک Composable فنکشن پیرامیٹر کو State<Int> کے طور پر اعلان کرتے ہیں، آپ ضمانت دیتے ہیں کہ جزو حالت کو پڑھ سکتا ہے لیکن بدل نہیں سکتا۔ MutableState مالک جزو کے اندر استعمال ہوتا ہے۔ یہ علاحدگی Compose کے بنیادی طریقہ کار میں سے ایک ہے جو غیر مجاز تبدیلیوں کو روکتا ہے۔
Compose میں حالت انٹرفیس کے درجہ بندی میں کئی سطح ہیں۔ سب سے اوپر State<T> ہے جیسمیں صرف پڑھنے کی value ہے۔ نیچے MutableState<T> ہے جیسمیں پڑھنے-لکھنے کی value ہے۔ اس کے نیچے مخصوصی اولی اقسام آتی ہیں: MutableIntState، MutableFloatState، MutableLongState، MutableBooleanState اور دیگر، جو اولی کی باکسنگ سے بچتے ہیں۔
MutableDoubleState اور MutableLongState کم عام ہیں لیکن موجود ہیں۔ مجموعہ انٹرفیس: MutableListState — فہرست کے اندر تبدیلیوں کو ٹریک کرنے کے لیے، MutableStateMap — میپ کے لیے۔ انمیں سے ہر انٹرفیس ایک مخصوص منظرنامے کے لیے بہترین کیا گیا ہے اور اضافی مجموعہ ہرافی کے طریقوں کے ساتھ بنیادی MutableState کو وسیع کرتا ہے۔
SnapshotStateList اور SnapshotStateMap snapshot کے ساتھ مطابق قابل تبدیل فہرستوں اور میپ کے نفاذ ہیں۔ یہ صرف قدر کی بدلائی ہی نہیں بلکہ اندرونی تبدیلیوں کو بھی ٹریک کر سکتے ہیں: فہرست میں اتم شامل کرنا، حذف کرنا، موجودہ اتم کو ترمیم کرنا۔ ان ساختوں کے لیے، mutableStateListOf() اور mutableStateMapOf() متبقہ قابل مشاہدہ مجموعے بناتے ہیں۔
| انٹرفیس | مقصد | تخلیق کا طریقہ |
|---|---|---|
| State<T> | صرف پڑھنے کا کنٹینر | — |
| MutableState<T> | پڑھنے-لکھنے کا کنٹینر | mutableStateOf() |
| MutableIntState | باکسنگ کے بغیر اولی Int | mutableIntStateOf() |
| MutableFloatState | باکسنگ کے بغیر اولی Float | mutableFloatStateOf() |
| SnapshotStateList | قابل مشاہدہ فہرست | mutableStateListOf() |
| SnapshotStateMap | قابل مشاہدہ میپ | mutableStateMapOf() |
SnapshotMutationPolicy ایک انٹرفیس ہے جو یہ طے کرتا ہے کہ MutableState میں تبدیلی کب اہم سمجھی جاتی ہے۔ mutableStateOf دوسرے انداز کے طور پر policy قبول کرتا ہے۔ معیاری نفاذ: structuralEquality() (equals)، referentialEquality() (===)، neverEqualPolicy() (تبدیلی کو ہمیشہ اہم سمجھتا ہے)۔ کسٹم منطق کے لیے آپ اپنی پالیسی نفذ کر سکتے ہیں۔
structuralEquality() — طرحی رویہ۔ Compose نئی قدر کا پرانے سے equals() کے ذریعے موازنہ کرتا ہے۔ اگر نتیجہ true ہے، دوبارہ ترتیب نہیں چالو ہوتا۔ یہ اولی اقسام اور data class کے لیے آسان ہے، جہاں یکساں فیلڈ کے دو نمونوں کو برابر سمجھا جاتا ہے۔ مسئلہ: اگر data class میں ایک List ہے، equals() گہرائی موازنہ کرتا ہے، جو بڑی فہرستوں کے لیے مہنگا ہو سکتا ہے۔
referentialEquality() — === کے ذریعے حوالوں کا موازنہ کرتا ہے۔ دوبارہ ترتیب صرف اس وقت چالو ہوتی ہے جب ایک مختلف آبجیکٹ مقرر کیا جاتا ہے، چاہے مواد یکساں ہی کیوں نہ ہو۔ یہ ناقابل تبدیل data class کے لیے بہترین ہے جہاں ہر نائے نمونہ ایک تبدیلی کی ضمانت دیتا ہے۔ neverEqualPolicy() — موازنہ کیئے بغیر تبدیلی کو ہمیشہ اہم سمجھتا ہے۔ مفید ہے جب setter شازہ بلایا جاتا ہے اور equals پر وقت صرف کرنے کی ضرورت نہیں ہے۔
// Policy comparison in practice
data class User(val name: String, val age: Int)
@Composable
fun UserProfile() {
// structuralEquality: recomposition ONLY if data changed
var user1 by remember {
mutableStateOf(User("Alice", 30))
}
// referentialEquality: recomposition on ANY assignment
var user2 by remember {
mutableStateOf(User("Bob", 25),
SnapshotMutationPolicy.referentialEquality())
}
// user1: copy() with same fields does NOT trigger recomposition
// user2: even user2.copy() == user2 triggers recomposition (new ref)
}
اولی MutableIntState اور مشابہ مخصوصی انٹرفیس ہیں جو باکسنگ کے بغیر اولی قدروں کو ذخیرہ کرتے ہیں۔ ایک عام MutableState<Int> Int کو Integer کے طور پر ذخیرہ کرتا ہے، جو ہر لیکھنے پر ہیپ پر ایک آبجیکٹ بناتا ہے۔ MutableIntState int (اولی) کو ذخیرہ کرتا ہے، باکسنگ کے اورہیڈ کو مکمل طور پر ختم کرتا ہے۔ یہ اعلی تکرار کی اپڈیٹ کے لیے خاص طور پر اہم ہے — کاؤنٹر، اسکرول مقامات، اینیمیشن قدریں۔
mutableIntStateOf()، mutableFloatStateOf()، mutableLongStateOf() — فنکشنز جو اولی MutableState بناتے ہیں۔ انٹرفیس کو MutableIntState، MutableFloatState، MutableLongState کہا جاتا ہے۔ یہ بالترتیب MutableState<Int>، MutableState<Float> اور MutableState<Long> کو وسیع کرتے ہیں، اولی تیز رسائی کے لیے intValue پراپرٹی شامل کرتے ہیں۔ ان کا اندرونی نفاذ بغیر قفل پڑھنے/لکھنے کے لیے AtomicInteger استعمال کرتا ہے۔
استعمال: کاؤنٹر (Int)، اسکرول مقامات (Float offset)، وقتی ٹیکس (Long)۔ زیادہ تر روزمرہ مناظر میں کارکردگی کا فرق قابل توجہ نہیں ہے، لیکن ہزاروں اتم اور تبدیلی اینیمیشن کے ساتھ LazyList میں، اولی State ایک قابل قدر بہتری فراہم کرتا ہے۔ Google کا مشورہ ہے کہ عام mutableStateOf کے بجائے معیاری مناظر کے لیے اولی State استعمال کیا جائے۔
@Composable
fun ScrollCounter() {
// Bad: boxing on every update
var badCount by remember { mutableStateOf(0) }
// Good: no boxing, primitive storage
var goodCount by remember { mutableIntStateOf(0) }
// Usage is identical
Button(onClick = { goodCount++ }) {
Text("Count: $goodCount")
}
}
ایک TodoList جزو پر غور کریں، جہاں MutableState کو دو صورتوں میں استعمال کیا جاتا ہے: انپٹ حالت کے لیے علاحدہ متغیرات اور ایک متحرک کام کی فہرست کے لیے SnapshotStateList کے طور پر۔ دونوں کوڈ کی مختصری کے لیے وکالت کا استعمال کرتے ہیں۔
data class TodoItem(val id: Int, val text: String, val isDone: Boolean = false)
@Composable
fun TodoScreen() {
var inputText by remember { mutableStateOf("") }
val items = remember { mutableStateListOf() }
Column(modifier = Modifier.padding(16.dp)) {
Row {
TextField(
value = inputText,
onValueChange = { inputText = it }
)
Button(onClick = {
if (inputText.isNotBlank()) {
items.add(TodoItem(items.size, inputText))
inputText = ""
}
}) { Text("Add") }
}
LazyColumn {
items(items) { item ->
Row(modifier = Modifier.fillMaxWidth().clickable {
val idx = items.indexOf(item)
items[idx] = item.copy(isDone = !item.isDone)
}) {
Checkbox(checked = item.isDone, onCheckedChange = null)
Text(item.text)
}
}
}
}
}
mutableStateListOf ایک SnapshotStateList بناتا ہے — ایک قابل تبدیل فہرست جو انفرادی اتم میں تبدیلیوں کو ٹریک کرتی ہے۔ جب items.add() اور items[n] = newValue بلایا جاتا ہے، Compose تبدیلی کو دیکھتا ہے اور LazyColumn کے صرف انہیں اتم کو دوبارہ ترتیب دیتا ہے جو بدل گئے ہیں۔ inputText ایک عام MutableState<String> ہے۔ دو MutableState اقسام (انفرادی اور مجموعہ) کا امتزاج فارم اور فہرستوں والی سکرینوں کے لیے ایک معیاری پیٹرن ہے۔
اکثر پوچے جانے والے سوالات
MutableState remember کے بغیر ہر دوبارہ ترتیب پر نئے سرے بنے گا۔ mutableStateOf کی ہر نئی کل ایک نئا آبجیکٹ بناتی ہے، اور پرانی قدر گم ہو جاتی ہے۔ State کو دوبارہ ترتیبوں کے درمیان محفوظ رکھنے کے لیے ہمیشہ remember استعمال کریں، جب تک کہ State Composable کے باہر (مثال ViewModel میں) نہ بنایا گیا ہو۔
snapshot { } کے ذریعے snapshot کے باہر .value کو ایک بار پڑھیں۔ لیکن یہ ری اکٹوٹی کو منتفی کر دیتا ہے — تبدیلیاں آئندہ دوبارہ ترتیب کو متحرک نہیں کریں گیں۔ رکابت کے بغیر ایک بار پڑھنے کے لیے، بغیر پڑھے snapshot کے اندر currentValue() استعمال کریں۔
mutableIntStateOf تیز ہے کیونکہ اسے int کو Integer میں باکس کرنے کی ضرورت نہیں ہے۔ فی سیکنڈ ہزاروں اپڈیٹ (اینیمیشن، اسکرولنگ) کے ساتھ، تخصیص کے وقت میں فرق 30-50% تک پہنچ سکتا ہے۔ نادر اپڈیٹ (کلکس، ٹیکسٹ انپٹ) کے لیے، فرق ناچیز ہے۔
ممکن ہے لیکن سفارش نہیں کی جاتی۔ MutableState کے بجائے، State (صرف پڑھنے کے لیے) + onValueChange لیمبڈا پاس کریں۔ یہ State Hoisting پیٹرن نفذ کرتا ہے اور جزو کو دوبارہ استعمال قابل بناتا ہے۔ MutableState قبول کرنے والے اجزاء یک جہتی ڈیٹا بہاو کی خلاف ورزی کرتے ہیں۔
MutableState انٹرفیس کو نفذ کریں اور getter اور setter کے ساتھ override var value فراہم کریں۔ setter میں آپ توثیق یا لاگنگ شامل کر سکتے ہیں۔ Compose Runtime کے ساتھ پشت سرگێ مطابقت کے لیے، اپنے کسٹم نفاذ کو snapshotFlow میں لپیٹیں یا snapshotIncrement استعمال کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں