Files
06-compose-state/README.md
2026-06-07 06:26:57 +00:00

369 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 1. مشکل از کجا شروع شد؟
قبل از Jetpack Compose در اندروید، وقتی داده‌ای در برنامه تغییر می‌کرد باید **خودمان دستی UI را آپدیت می‌کردیم**.
مثال:
کاربر روی دکمه افزایش کلیک می‌کند → مقدار عدد تغییر می‌کند → باید TextView را هم تغییر دهیم.
در View های قدیمی:
```kotlin
count++
textView.text = count.toString()
```
یعنی برنامه‌نویس **باید یادش بماند UI را هم آپدیت کند**.
مشکل‌ها:
- ممکن است فراموش کنیم UI را آپدیت کنیم
- کدها پیچیده می‌شوند
- نگهداری سخت می‌شود
---
# 2. راه‌حل Compose چیست؟
در Compose یک قانون مهم داریم:
**UI باید تابعی از State باشد**
یعنی:
```
UI = f(state)
```
اگر state تغییر کند → UI خودش دوباره ساخته می‌شود.
به این فرایند می‌گوییم:
**Recomposition**
---
# 3. State چیست؟
State یعنی:
**داده‌ای که اگر تغییر کند، UI باید تغییر کند.**
مثال‌ها:
- مقدار counter
- متن داخل TextField
- وضعیت لودینگ
- لیست پیام‌ها
- وضعیت لاگین کاربر
مثال ساده:
```kotlin
var count = 0
```
اگر مقدار `count` تغییر کند، UI باید تغییر کند.
اما Compose از تغییر این متغیر خبر ندارد.
پس باید از **State مخصوص Compose** استفاده کنیم.
---
# 4. mutableStateOf چیست؟
برای اینکه Compose بفهمد داده تغییر کرده باید از **State Object** استفاده کنیم.
یکی از مهم‌ترین آن‌ها:
```
mutableStateOf
```
مثال:
```kotlin
var count = mutableStateOf(0)
```
اینجا count یک **State** است.
برای دسترسی به مقدار:
```
count.value
```
مثال:
```kotlin
count.value++
```
وقتی مقدار تغییر کند:
Compose متوجه می‌شود → UI دوباره ساخته می‌شود.
---
# 5. استفاده از State در Compose
یک مثال ساده Counter:
```kotlin
@Composable
fun CounterScreen() {
var count = remember { mutableStateOf(0) }
Column {
Text(text = "Count: ${count.value}")
Button(onClick = {
count.value++
}) {
Text("Increase")
}
}
}
```
اتفاقی که می‌افتد:
1⃣ صفحه ساخته می‌شود
2⃣ مقدار count = 0
3⃣ Text مقدار 0 را نشان می‌دهد
4⃣ کاربر دکمه را می‌زند
5⃣ مقدار count تغییر می‌کند
6⃣ Compose تشخیص می‌دهد state تغییر کرده
7⃣ UI دوباره اجرا می‌شود
این فرایند همان **Recomposition** است.
---
# 6. Recomposition چیست؟
**Recomposition یعنی اجرای دوباره Composable ها وقتی State تغییر می‌کند.**
در مثال قبل:
وقتی:
```
count.value++
```
اجرا می‌شود
Compose:
- متوجه تغییر state می‌شود
- Composable مربوطه را دوباره اجرا می‌کند
- UI جدید رسم می‌شود
نکته مهم:
Compose **کل صفحه را دوباره نمی‌سازد**
فقط بخش‌هایی که نیاز دارند دوباره اجرا می‌شوند.
---
# 7. remember چیست؟
یک مشکل مهم وجود دارد.
اگر این کد را بنویسیم:
```kotlin
var count = mutableStateOf(0)
```
در هر Recomposition مقدار دوباره **0 می‌شود**.
چرا؟
چون تابع دوباره اجرا می‌شود.
برای حل این مشکل از:
```
remember
```
استفاده می‌کنیم.
```kotlin
var count = remember { mutableStateOf(0) }
```
remember باعث می‌شود:
✅ مقدار بین recomposition ها حفظ شود.
---
# 8. روش بهتر: by delegation
نوشتن `.value` کمی آزاردهنده است.
روش بهتر:
```kotlin
var count by remember { mutableStateOf(0) }
```
حالا می‌توانیم مستقیم استفاده کنیم:
```kotlin
count++
```
مثال کامل:
```kotlin
@Composable
fun CounterScreen() {
var count by remember { mutableStateOf(0) }
Column {
Text(text = "Count: $count")
Button(onClick = {
count++
}) {
Text("Increase")
}
}
}
```
---
# 9. جریان کامل اتفاقات
مراحل اجرای برنامه:
1⃣ Composable اجرا می‌شود
2⃣ State ساخته می‌شود
3⃣ UI بر اساس State ساخته می‌شود
وقتی کاربر دکمه را می‌زند:
4⃣ State تغییر می‌کند
5⃣ Compose تغییر را تشخیص می‌دهد
6⃣ Recomposition انجام می‌شود
7⃣ UI جدید ساخته می‌شود
---
# 10. مثال Counter کامل
```kotlin
@Composable
fun CounterScreen() {
var count by remember { mutableStateOf(0) }
Column {
Text(
text = "Count: $count",
fontSize = 30.sp
)
Button(
onClick = { count++ }
) {
Text("Increase")
}
Button(
onClick = { count-- }
) {
Text("Decrease")
}
}
}
```
---
# 11. نکات مهم
✅ State داده‌ای است که UI به آن وابسته است.
✅ وقتی State تغییر کند → Recomposition اتفاق می‌افتد.
✅ برای تعریف State از `mutableStateOf` استفاده می‌کنیم.
✅ برای حفظ مقدار در Recomposition از `remember` استفاده می‌کنیم.
✅ بهتر است از `by` استفاده کنیم تا `.value` حذف شود.
---
# 12. تمرین برای دانشجویان
1⃣ یک Counter بسازید که دکمه‌های زیر داشته باشد:
- Increase
- Decrease
- Reset
2⃣ اگر مقدار Counter به **10 رسید** یک متن نمایش دهید:
```
Maximum reached!
```
3⃣ اگر مقدار Counter **منفی شد** رنگ متن قرمز شود.
---
# 13. چالش فکری
اگر به جای State این کد را بنویسیم:
```kotlin
var count = 0
```
و در Button مقدار را زیاد کنیم:
```
count++
```
آیا UI تغییر می‌کند؟
چرا؟
---
پاسخ:
خیر. چون Compose از تغییر این متغیر خبر ندارد. بنابراین Recomposition اتفاق نمی‌افتد.
---
# جمع‌بندی
مهم‌ترین مفاهیم Compose:
- State → داده قابل تغییر UI
- mutableStateOf → ساخت state
- remember → نگهداری مقدار در recomposition
- Recomposition → اجرای دوباره UI بعد از تغییر state
قانون اصلی Compose:
**UI تابعی از State است.**