יצירת מודלים של צפייה עם יחסי תלות חלק מ-Android Jetpack.
בהתאם לשיטות המומלצות של החדרת תלות, ViewModels יכול
מקבלים יחסי תלות כפרמטרים ב-constructor שלהם. אלה בעיקר סוגים
מהשכבות דומיין או נתונים. מכיוון שה-framework מספק
Viewmodels – יש צורך במנגנון מיוחד כדי ליצור מופעים שלהם. ש
הוא הממשק ViewModelProvider.Factory
. הטמעות בלבד
בממשק הזה יכול ליצור מודלים של ViewModel בהיקף הנכון.
הצגת מודלים עם CreationExtras
אם מחלקה של ViewModel מקבלת יחסי תלות ב-constructor שלה, צריך לציין מפעל
שבה מוטמע הממשק 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()
.createSavedStateHandle())
ומעבירים אותו ל-ViewModel.
הדוגמה הבאה היא איך לספק מופע של ViewModel
לוקח מאגר בהיקף של הכיתה Application
SavedStateHandle
כיחסי תלות:
Kotlin
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.CreationExtras
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 = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>,
extras: CreationExtras
): T {
// Get the Application object from extras
val application = checkNotNull(extras[APPLICATION_KEY])
// Create a SavedStateHandle for this ViewModel from extras
val savedStateHandle = extras.createSavedStateHandle()
return MyViewModel(
(application as MyApplication).myRepository,
savedStateHandle
) as T
}
}
}
}
Java
import static androidx.lifecycle.SavedStateHandleSupport.createSavedStateHandle;
import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY;
import androidx.lifecycle.SavedStateHandle;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.viewmodel.ViewModelInitializer;
public class MyViewModel extends ViewModel {
public MyViewModel(
MyRepository myRepository,
SavedStateHandle savedStateHandle
) { /* Init ViewModel here */ }
static final ViewModelInitializer<MyViewModel> initializer = new ViewModelInitializer<>(
MyViewModel.class,
creationExtras -> {
MyApplication app = (MyApplication) creationExtras.get(APPLICATION_KEY);
assert app != null;
SavedStateHandle savedStateHandle = createSavedStateHandle(creationExtras);
return new MyViewModel(app.getMyRepository(), savedStateHandle);
}
);
}
לאחר מכן, אפשר להשתמש במפעל הזה לאחזור מופע של ViewModel:
Kotlin
import androidx.activity.viewModels
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels { MyViewModel.Factory }
// Rest of Activity code
}
Java
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
public class MyActivity extends AppCompatActivity {
MyViewModel myViewModel = new ViewModelProvider(
this,
ViewModelProvider.Factory.from(MyViewModel.initializer)
).get(MyViewModel.class);
// Rest of Activity code
}
Jetpack פיתוח נייטיב
import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
modifier: Modifier = Modifier,
viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
// ...
}
לחלופין, אפשר להשתמש ב-DSL במפעל ViewModel כדי ליצור מפעלים idiomatic Kotlin API:
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
)
}
}
}
}
מפעלים לגרסת ViewModel מלפני יותר מ-2.5.0
אם אתם משתמשים בגרסה של ViewModel בגרסה ישנה יותר מ-2.5.0, צריך לספק
מפעלים מקבוצת משנה של מחלקות שמתרחבות אל ViewModelProvider.Factory
ולהטמיע את הפונקציה create(Class<T>)
. בהתאם ליחסי התלות
לצרכים של ה-ViewModel, יש להרחיב מחלקה אחרת מ:
AndroidViewModelFactory
אם יש צורך במחלקהApplication
.AbstractSavedStateViewModelFactory
אםSavedStateHandle
צריך יועברו בתור תלות.
אם אין צורך ב-Application
או ב-SavedStateHandle
, אפשר פשוט להרחיב מ-
ViewModelProvider.Factory
.
הדוגמה הבאה משתמשת ב-AbstractSavedStateViewModelFactory
עבור
ViewModel לוקח מאגר וסוג SavedStateHandle
בתור
של תלות:
Kotlin
class MyViewModel(
private val myRepository: MyRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
// ViewModel logic ...
// Define ViewModel factory in a companion object
companion object {
fun provideFactory(
myRepository: MyRepository,
owner: SavedStateRegistryOwner,
defaultArgs: Bundle? = null,
): AbstractSavedStateViewModelFactory =
object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return MyViewModel(myRepository, handle) as T
}
}
}
}
Java
import androidx.annotation.NonNull;
import androidx.lifecycle.AbstractSavedStateViewModelFactory;
import androidx.lifecycle.SavedStateHandle;
import androidx.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
public MyViewModel(
MyRepository myRepository,
SavedStateHandle savedStateHandle
) { /* Init ViewModel here */ }
}
public class MyViewModelFactory extends AbstractSavedStateViewModelFactory {
private final MyRepository myRepository;
public MyViewModelFactory(
MyRepository myRepository
) {
this.myRepository = myRepository;
}
@SuppressWarnings("unchecked")
@NonNull
@Override
protected <T extends ViewModel> T create(
@NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle
) {
return (T) new MyViewModel(myRepository, handle);
}
}
לאחר מכן, אפשר להשתמש בהגדרות היצרן כדי לאחזר את ה-ViewModel:
Kotlin
import androidx.activity.viewModels
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels {
MyViewModel.provideFactory((application as MyApplication).myRepository, this)
}
// Rest of Activity code
}
Java
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
public class MyActivity extends AppCompatActivity {
MyViewModel myViewModel = new ViewModelProvider(
this,
ViewModelProvider.Factory.from(MyViewModel.initializer)
).get(MyViewModel.class);
// Rest of Activity code
}
Jetpack פיתוח נייטיב
import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
modifier: Modifier = Modifier,
viewModel: MyViewModel = viewModel(
factory = MyViewModel.provideFactory(
(LocalContext.current.applicationContext as MyApplication).myRepository,
owner = LocalSavedStateRegistryOwner.current
)
)
) {
// ...
}
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- מודול מצב שמור ל-ViewModel
- שמירת מצבים בממשק המשתמש
- סקירה כללית של LiveData