Bağımlılıklar içeren ViewModel'ler oluşturma Android Jetpack'in bir parçasıdır.
Bağımlılık ekleme en iyi uygulamalarına göre ViewModel'ler, yapıcılarında parametre olarak bağımlılık alabilir. Bunlar genellikle alan veya veri katmanlarından türetilmiş türlerdir. Çerçeve, ViewModel'leri sağladığından bunların örneklerini oluşturmak için özel bir mekanizma gerekir. Bu mekanizma, ViewModelProvider.Factory
arayüzüdür. Yalnızca bu arayüzün uygulamalarında ViewModel'ler doğru kapsamda oluşturulabilir.
CreationExtras içeren ViewModeller
ViewModel
sınıfı oluşturucusunda bağımlılıklar alıyorsa ViewModelProvider.Factory
arayüzünü uygulayan bir fabrika sağlayın.
ViewModel'in yeni bir örneğini sağlamak için create(Class<T>, CreationExtras)
işlevini geçersiz kılın.
CreationExtras
, bir ViewModel'i örneklemeye yardımcı olan alakalı bilgilere erişmenize olanak tanır. Ek özelliklerden erişilebilen anahtarların listesi aşağıda verilmiştir:
Anahtar | Uygulama işlevi |
---|---|
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY |
ViewModelProvider.get() 'e ilettiğiniz özel anahtara erişim sağlar. |
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY |
Application sınıfının örneğine erişim sağlar. |
SavedStateHandleSupport.DEFAULT_ARGS_KEY |
SavedStateHandle oluşturmak için kullanmanız gereken bağımsız değişken grubuna erişim sağlar. |
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY |
ViewModel oluşturmak için kullanılan SavedStateRegistryOwner 'e erişim sağlar. |
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY |
ViewModel oluşturmak için kullanılan ViewModelStoreOwner 'e erişim sağlar. |
Yeni bir SavedStateHandle
örneği oluşturmak için CreationExtras.createSavedStateHandle()
işlevini kullanıp ViewModel'e iletin.
APPLICATION_KEY ile CreationExtras
Aşağıda, bağımlılık olarak Application
sınıfı ve SavedStateHandle
kapsamındaki bir depoyu kullanan bir ViewModel
örneğinin nasıl sağlanacağına dair bir örnek verilmiştir:
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);
}
);
}
Ardından, ViewModel örneğini alırken bu fabrikayı kullanabilirsiniz:
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 Compose
import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
modifier: Modifier = Modifier,
viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
// ...
}
Alternatif olarak, daha doğal bir Kotlin API'si kullanarak fabrikalar oluşturmak için ViewModel
fabrika DSL'sini kullanın:
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
)
}
}
}
}
Özel parametreleri CreationExtras olarak iletme
Özel bir anahtar oluşturarak bağımlılıkları CreationExtras
üzerinden ViewModel
'ünüze iletebilirsiniz.
ViewModel
, Application
sınıfı ve APPLICATION_KEY
aracılığıyla erişilemeyen nesnelere bağlıysa bu yöntem işinize yarayabilir. ViewModel
öğenizin bir Kotlin Multiplatform modülü içinde oluşturulması ve bu nedenle Android bağımlılıklarına erişiminin olmaması buna örnek olarak gösterilebilir.
Bu örnekte ViewModel
, özel bir anahtar tanımlar ve bunu ViewModelProvider.Factory
içinde kullanır.
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,
)
}
}
}
}
ComponentActivity
, Fragment
veya NavBackStackEntry
gibi bir ViewModelStoreOwner
'ten veya Jetpack Compose ile ViewModel
sınıfını CreationExtras.Key
kullanarak örneklendirebilirsiniz.
Kotlin
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]
Jetpack Compose
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,
)
}
2.5.0'dan daha eski ViewModel sürümü için fabrikalar
ViewModel
'nin 2.5.0'den eski bir sürümünü kullanıyorsanız ViewModelProvider.Factory
'yi genişleten ve create(Class<T>)
işlevini uygulayan bir sınıf alt kümesinden fabrikalar sağlamanız gerekir. ViewModel
'ün ihtiyaç duyduğu bağımlılıklara bağlı olarak farklı bir sınıfın genişletilmesi gerekir:
Application
sınıfı gerekiyorsaAndroidViewModelFactory
.SavedStateHandle
öğesinin bağımlılık olarak iletilmesi gerekiyorsaAbstractSavedStateViewModelFactory
.
Application
veya SavedStateHandle
gerekmiyorsa ViewModelProvider.Factory
'den uzatın.
Aşağıdaki örnekte, depoyu alan bir ViewModel için AbstractSavedStateViewModelFactory
ve bağımlılık olarak bir SavedStateHandle
türü kullanılmaktadır:
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);
}
}
Ardından, ViewModel'inizi almak için factory'yi kullanabilirsiniz:
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 Compose
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
)
)
) {
// ...
}
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- ViewModel için Kayıtlı Durum modülü
- Kullanıcı arayüzü durumlarını kaydetme
- LiveData'ya genel bakış