Создание моделей представления с зависимостями . Часть Android Jetpack .

Следуя лучшим практикам внедрения зависимостей , ViewModels могут принимать зависимости в качестве параметров в своем конструкторе. В основном это типы из предметной области или слоев данных . Поскольку платформа предоставляет ViewModels, для создания их экземпляров требуется специальный механизм. Этот механизм — интерфейс ViewModelProvider.Factory . Только реализации этого интерфейса могут создавать экземпляры ViewModels в нужной области видимости .

Модели просмотра с CreationExtras

Если класс ViewModel получает зависимости в своем конструкторе, предоставьте фабрику, реализующую интерфейс 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 в качестве зависимостей:

    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
               
}
           
}
       
}
   
}
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:

import androidx.activity.viewModels

class MyActivity : AppCompatActivity() {

   
private val viewModel: MyViewModel by viewModels { MyViewModel.Factory }

   
// Rest of Activity code
}
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
}
import androidx.lifecycle.viewmodel.compose.viewModel

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

В качестве альтернативы используйте фабричный DSL ViewModel для создания фабрик с использованием более идиоматического API 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.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, необходимо расширить другой класс:

Если Application или SavedStateHandle не нужны, просто расширьте ViewModelProvider.Factory .

В следующем примере используется AbstractSavedStateViewModelFactory для ViewModel, который принимает репозиторий и тип SavedStateHandle в качестве зависимости:

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
           
}
       
}
   
}
}
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:

import androidx.activity.viewModels

class MyActivity : AppCompatActivity() {

   
private val viewModel: MyViewModel by viewModels {
       
MyViewModel.provideFactory((application as MyApplication).myRepository, this)
   
}

   
// Rest of Activity code
}
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
}
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
       
)
   
)
) {
   
// ...
}
{% дословно %}

Пока рекомендаций нет.

Попытайтесь в свой аккаунт Google.

{% дословно %}