ViewModels mit Abhängigkeiten erstellen (Ansichten) Teil von Android Jetpack.
Konzepte und Jetpack Compose-Implementierung
Gemäß den Best Practices für die Abhängigkeitsinjektion können ViewModels
Abhängigkeiten als Parameter in ihrem Konstruktor verwenden. Dabei handelt es sich meist um Typen
aus den Domain- oder Datenschichten. Da das Framework die ViewModels bereitstellt, ist ein spezieller Mechanismus erforderlich, um Instanzen davon zu erstellen. Dieser Mechanismus ist die ViewModelProvider.Factory-Schnittstelle. Nur Implementierungen dieser Schnittstelle können ViewModels im richtigen Bereich instanziieren.
ViewModels mit CreationExtras
Wenn eine ViewModel-Klasse Abhängigkeiten in ihrem Konstruktor empfängt, stellen Sie eine
Factory bereit, die die ViewModelProvider.Factory-Schnittstelle implementiert.
Überschreiben Sie die create(Class<T>, CreationExtras) Funktion, um eine
neue Instanz des ViewModel bereitzustellen.
CreationExtras mit APPLICATION_KEY
Im Folgenden finden Sie ein Beispiel dafür, wie Sie eine Instanz eines ViewModel bereitstellen, das
ein Repository mit dem Bereich der Application Klasse und
SavedStateHandle als Abhängigkeiten verwendet:
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);
}
);
}
Anschließend können Sie diese Factory verwenden, wenn Sie eine Instanz des ViewModel abrufen:
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
}
Benutzerdefinierte Parameter als CreationExtras übergeben
Sie können Abhängigkeiten über CreationExtras an Ihr ViewModel übergeben, indem Sie einen benutzerdefinierten Schlüssel erstellen.
Das kann nützlich sein, wenn Ihr ViewModel von Objekten abhängt, auf die nicht über die Application-Klasse und APPLICATION_KEY zugegriffen werden kann. Ein Beispiel dafür ist, wenn Ihr ViewModel in einem Kotlin Multiplatform-Modul erstellt wird und daher keinen Zugriff auf Android-Abhängigkeiten hat.
In diesem Beispiel definiert das ViewModel einen benutzerdefinierten Schlüssel und verwendet ihn in der
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 for your dependency
val MY_REPOSITORY_KEY = object : 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,
)
}
}
}
}
Sie können ein ViewModel mit einem CreationExtras.Key aus einem
ViewModelStoreOwner wie
ComponentActivity, Fragment, oder NavBackStackEntry instanziieren.
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.MutableCreationExtras
// ...
// Use from ComponentActivity, Fragment, NavBackStackEntry,
// or another ViewModelStoreOwner.
val viewModelStoreOwner: ViewModelStoreOwner = this
val myViewModel: MyViewModel = ViewModelProvider.create(
viewModelStoreOwner,
factory = MyViewModel.Factory,
extras = MutableCreationExtras().apply {
set(MyViewModel.MY_REPOSITORY_KEY, myRepository)
},
)[MyViewModel::class]
Factories für ViewModel-Versionen vor 2.5.0
Wenn Sie eine Version von ViewModel vor 2.5.0 verwenden, müssen Sie
Factories aus einer Teilmenge von Klassen bereitstellen, die ViewModelProvider.Factory
erweitern und die Funktion create(Class<T>) implementieren. Je nachdem, welche Abhängigkeiten das ViewModel benötigt, muss eine andere Klasse erweitert werden:
AndroidViewModelFactory, wenn dieApplication-Klasse erforderlich ist.AbstractSavedStateViewModelFactory, wennSavedStateHandleals Abhängigkeit übergeben werden muss.
Wenn Application oder SavedStateHandle nicht erforderlich sind, erweitern Sie einfach ViewModelProvider.Factory.
Im folgenden Beispiel wird eine AbstractSavedStateViewModelFactory für ein
ViewModel verwendet, das ein Repository und einen SavedStateHandle-Typ als
Abhängigkeit verwendet:
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);
}
}
Anschließend können Sie die Factory verwenden, um Ihr ViewModel abzurufen:
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
}
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist
- Modul für gespeicherten Status für ViewModel
- UI-Status speichern
- LiveData – Übersicht