יצירת ViewModels עם יחסי תלות   בארגז הכלים Android Jetpack.

בהתאם לשיטות המומלצות של הזרקת תלות, אפשר להעביר את התלות כפרמטרים בבנאי של ViewModels. רובם הם מסוגים של שכבות הדומיין או הנתונים. מכיוון שה-ViewModels מסופקים על ידי המסגרת, נדרש מנגנון מיוחד כדי ליצור מופעים שלהם. המנגנון הזה הוא ממשק ViewModelProvider.Factory. רק הטמעות של הממשק הזה יכולות ליצור מופעים של ViewModels בהיקף הנכון.

‫ViewModels עם CreationExtras

אם מחלקה ViewModel מקבלת תלויות ב-constructor שלה, צריך לספק פקטורי (factory) שמטמיע את הממשק ViewModelProvider.Factory. מבטלים את ההגדרה של הפונקציה create(Class<T>, CreationExtras) כדי לספק מופע חדש של ViewModel.

CreationExtras מאפשר לכם לגשת למידע רלוונטי שעוזר ליצור ViewModel. זו רשימה של מפתחות שאפשר לגשת אליהם מהתוספים:

מפתח פונקציונליות
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY השירות הזה מספק גישה למפתח המותאם אישית שהעברתם אל ViewModelProvider.get().
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY הפונקציה מספקת גישה למופע של המחלקה Application.
SavedStateHandleSupport.DEFAULT_ARGS_KEY הפונקציה מספקת גישה לחבילת הארגומנטים שבהם צריך להשתמש כדי ליצור את SavedStateHandle.
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY מספק גישה ל-SavedStateRegistryOwner שמשמש לבניית ViewModel.
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY מספק גישה ל-ViewModelStoreOwner שמשמש לבניית ViewModel.

כדי ליצור מופע חדש של SavedStateHandle, משתמשים בפונקציה CreationExtras.createSavedStateHandle() ומעבירים אותה אל ViewModel.

‫CreationExtras עם APPLICATION_KEY

בדוגמה הבאה אפשר לראות איך מספקים מופע של ViewModel שמקבל מאגר בהיקף של המחלקה Application ו-SavedStateHandle כתלות:

    import androidx.lifecycle.SavedStateHandle
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.ViewModelProvider
    import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
    import androidx.lifecycle.createSavedStateHandle
    import androidx.lifecycle.viewmodel.initializer
    import androidx.lifecycle.viewmodel.viewModelFactory

    class MyViewModel(
        private val myRepository: MyRepository,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {

        // ViewModel logic
        // ...

        // Define ViewModel factory in a companion object
        companion object {

            val Factory: ViewModelProvider.Factory = viewModelFactory {
                initializer {
                    val savedStateHandle = createSavedStateHandle()
                    val myRepository = (this[APPLICATION_KEY] as MyApplication).myRepository
                    MyViewModel(
                        myRepository = myRepository,
                        savedStateHandle = savedStateHandle
                    )
                }
            }
        }
    }

אחר כך אפשר להשתמש בפקטורי (factory) הזה כשמאחזרים מופע של ViewModel:

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    modifier: Modifier = Modifier,
    viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
    // ...
}

העברה של פרמטרים מותאמים אישית כ-CreationExtras

אפשר להעביר תלויות אל ViewModel דרך CreationExtras על ידי יצירת מפתח מותאם אישית. האפשרות הזו שימושית אם ViewModel תלוי באובייקטים שלא נגישים דרך המחלקה Application ו-APPLICATION_KEY. דוגמה למצב כזה היא כש-ViewModel נוצר בתוך מודול Kotlin Multiplatform ולכן אין לו גישה לתלות ב-Android.

בדוגמה הזו, ViewModel מגדיר מפתח מותאם אישית ומשתמש בו ב-ViewModelProvider.Factory.

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory

class MyViewModel(
    private val myRepository: MyRepository,
) : ViewModel() {
    // ViewModel logic

    // Define ViewModel factory in a companion object
    companion object {

        // Define a custom key using the factory function
        val MY_REPOSITORY_KEY = CreationExtras.Key<MyRepository>()

        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                // Get the dependency in your factory
                val myRepository = this[MY_REPOSITORY_KEY] as MyRepository
                MyViewModel(
                    myRepository = myRepository,
                )
            }
        }
    }
}

אפשר ליצור מופע של ViewModel עם CreationExtras.Key ישירות בקומפוזיציות.

import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
// ...
@Composable
fun MyApp(myRepository: MyRepository) {
    val extras = MutableCreationExtras().apply {
        set(MyViewModel.MY_REPOSITORY_KEY, myRepository)
    }
    val viewModel: MyViewModel = viewModel(
        factory = MyViewModel.Factory,
        extras = extras,
    )
}

מקורות מידע נוספים

למידע נוסף על ViewModels ועל יחסי תלות, אפשר להיעזר במקורות המידע הנוספים הבאים:

תיעוד

צפייה בתוכן