Update README.md
This commit is contained in:
368
README.md
368
README.md
@@ -1,2 +1,368 @@
|
||||
# 06-compose-state
|
||||
|
||||
# 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 است.**
|
||||
|
||||
Reference in New Issue
Block a user