סקירה כללית של ViewModel (Views)
מושגים ויישום ב-Jetpack פיתוח נייטיב
המחלקות ViewModel הן מאחסני מצב ברמת המסך או ברמת הלוגיקה העסקית. הוא חושף את המצב לממשק המשתמש ומכיל לוגיקה עסקית קשורה.
היתרון העיקרי שלו הוא שהוא שומר במטמון את המצב וממשיך אותו גם אחרי שינויים בהגדרות. המשמעות היא שממשק המשתמש לא צריך לאחזר נתונים מחדש כשעוברים בין פעילויות או אחרי שינויים בהגדרות, למשל כשמסובבים את המסך.
היתרונות של ViewModel
החלופה ל-ViewModel היא מחלקה רגילה שמכילה את הנתונים שמוצגים בממשק המשתמש. הבעיה הזו יכולה לקרות כשעוברים בין פעילויות או בין יעדי ניווט. אם לא מאחסנים את הנתונים באמצעות מנגנון שמירת מצב המופע, הם נמחקים. ViewModel מספק API נוח להתמדת נתונים, שפותר את הבעיה הזו.
יש שני יתרונות עיקריים לשימוש במחלקה ViewModel:
- היא מאפשרת לכם לשמור את מצב ממשק המשתמש.
- הוא מספק גישה ללוגיקה עסקית.
היקף
כשיוצרים מופע של ViewModel, מעבירים לו אובייקט שמטמיע את הממשק ViewModelStoreOwner. יכול להיות שזה יעד ניווט, גרף ניווט, פעילות, קטע או כל סוג אחר שמטמיע את הממשק. לאחר מכן, ה-ViewModel מוגדר בהיקף של Lifecycle של ViewModelStoreOwner. הוא נשאר בזיכרון עד שViewModelStoreOwner
נעלם באופן סופי.
טווח של מחלקות הן מחלקות משנה ישירות או עקיפות של הממשק ViewModelStoreOwner. מחלקות המשנה הישירות הן ComponentActivity, Fragment ו-NavBackStackEntry.
רשימה מלאה של מחלקות משנה עקיפות זמינה בחומר העזר בנושא ViewModelStoreOwner.
הטמעה של ViewModel
הדוגמה הבאה היא הטמעה של ViewModel למסך שמאפשר למשתמש לגלגל קוביות.
Kotlin
data class DiceUiState(
val firstDieValue: Int? = null,
val secondDieValue: Int? = null,
val numberOfRolls: Int = 0,
)
class DiceRollViewModel : ViewModel() {
// Expose screen UI state
private val _uiState = MutableStateFlow(DiceUiState())
val uiState: StateFlow<DiceUiState> = _uiState.asStateFlow()
// Handle business logic
fun rollDice() {
_uiState.update { currentState ->
currentState.copy(
firstDieValue = Random.nextInt(from = 1, until = 7),
secondDieValue = Random.nextInt(from = 1, until = 7),
numberOfRolls = currentState.numberOfRolls + 1,
)
}
}
}
Java
public class DiceUiState {
private final Integer firstDieValue;
private final Integer secondDieValue;
private final int numberOfRolls;
// ...
}
public class DiceRollViewModel extends ViewModel {
private final MutableLiveData<DiceUiState> uiState =
new MutableLiveData(new DiceUiState(null, null, 0));
public LiveData<DiceUiState> getUiState() {
return uiState;
}
public void rollDice() {
Random random = new Random();
uiState.setValue(
new DiceUiState(
random.nextInt(7) + 1,
random.nextInt(7) + 1,
uiState.getValue().getNumberOfRolls() + 1
)
);
}
}
אפשר לגשת ל-ViewModel מפעילות באופן הבא:
Kotlin
import androidx.activity.viewModels
class DiceRollActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same DiceRollViewModel instance created by the first activity.
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
val viewModel: DiceRollViewModel by viewModels()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Update UI elements
}
}
}
}
}
Java
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
DiceRollViewModel model = new ViewModelProvider(this).get(DiceRollViewModel.class);
model.getUiState().observe(this, uiState -> {
// update UI
});
}
}
מומלץ בשבילך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- שימוש בשגרות משנה (coroutines) של Kotlin עם רכיבים שמודעים למחזור החיים
- שמירת מצבי ממשק המשתמש
- טעינה והצגה של נתונים עם חלוקה לדפים