依存関係を使用して ViewModel を作成する(ビュー) Android Jetpack の一部
依存関係注入のベスト プラクティスに基づいて、ViewModel は
コンストラクタのパラメータとして依存関係を取得できます。ほとんどの場合、これらはドメインレイヤまたはデータレイヤのタイプです。フレームワークは ViewModel を提供しているため、ViewModel のインスタンスを作成するには特別なメカニズムが必要です。そのメカニズムとは、ViewModelProvider.Factory インターフェースです。このインターフェースの実装のみが、適切なスコープで ViewModel をインスタンス化することができます 。
CreationExtras の ViewModel
ViewModel クラスがコンストラクタ内で依存関係を受け取る場合は、
ViewModelProvider.Factory インターフェースを実装するファクトリを提供してください。create(Class<T>, CreationExtras) 関数をオーバーライドして、ViewModel の
新しいインスタンスを提供します。
APPLICATION_KEY を使用した CreationExtras
次の例は、ViewModel が リポジトリ を Application クラスと SavedStateHandle を依存関係として取得する方法の例です。
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
}
カスタム パラメータを CreationExtras として渡す
カスタムキーを作成することで、CreationExtras を介して ViewModel に依存関係を渡すことができます。
これは、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 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、NavBackStackEntry などの
ViewModelStoreOwner から CreationExtras.Key を使用して ViewModel をインスタンス化できます。
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]
2.5.0 より前のバージョンの ViewModel のファクトリ
2.5.0 より前のバージョンの ViewModel を使用している場合は、
ViewModelProvider.Factory を拡張するクラスのサブセットのファクトリを提供し、create(Class<T>) 関数を実装する必要があります。ViewModel で必要となる依存関係に応じて、異なるクラスを拡張する必要があります。
AndroidViewModelFactory:Applicationクラスが必要な場合。AbstractSavedStateViewModelFactory:SavedStateHandleを依存関係として渡す必要がある場合。
Application または SavedStateHandle が不要な場合は、ViewModelProvider.Factory から拡張するだけです。
次の例では、リポジトリと SavedStateHandle タイプを依存関係として取得する ViewModel に対して AbstractSavedStateViewModelFactory を使用します。
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
}
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- ViewModel の保存済み状態のモジュール
- UI の状態を保存する
- LiveData の概要