はじめに
Android開発において、JetpackライブラリのViewModelは、今や当たり前のように利用されるお馴染みのコンポーネントです。特にKotlinを使用する場合、by viewModels() デリゲートプロパティを活用することで、ViewModelのインスタンス化と管理を非常に簡潔に行うことができます。
この便利な by viewModels() にはいくつかの種類が存在し、それぞれの状況に応じた適切な使い分けをすることで、より効果的に利用できます。この記事では、by viewModels() の基本的な使い方から、知っておくべき種類とそれらの使い分けについて詳しく解説します。ViewModelをより効果的に活用し、堅牢でメンテナンス性の高いAndroidアプリケーション開発を目指しましょう。
by viewModels()は主に3種類ある
- by viewModels()
- by activityViewModels()
- by navGraphViewModels()
これら3つのデリゲートプロパティの違いと使い方について説明します。
これらの委譲プロパティは、ViewModelの「スコープ」と「ライフサイクル」を決定する点で異なります。どのViewModelを使用すべきかは、データの共有範囲と、どのライフサイクルに紐付けるかによって決まります。
by viewModels()について
スコープ
各ActivityまたはFragmentのインスタンスに紐付きます。

ライフサイクル
そのActivityまたはFragmentのライフサイクルに完全に依存します。ActivityやFragmentが破棄されると、対応するViewModelも同時に破棄されます。
使い方
ActivityやFragmentが他のコンポーネントと独立した独自のデータを持ちたい場合に、最も一般的に使用されます。
// Activityで使用する場合
class MyActivity : AppCompatActivity() {
private val viewModel: MyActivityViewModel by viewModels()
// ...
}
// Fragmentで使用する場合
class MyFragment : Fragment() {
private val viewModel: MyFragmentViewModel by viewModels()
// ...
}
by activityViewModels()
スコープ
ライフサイクル
親Activityのライフサイクルに依存します。親Activityが破棄されるまで、ViewModelは生存し続けます。
使い方
複数のFragmentが親Activityに共通のデータを共有したい場合に便利です。
親Activity内の異なるFragment間でデータをやり取りしたり、Activity全体の状態を管理したりするのに適しています。
class ParentActivity : AppCompatActivity() {
// ActivityViewModelは通常、Fragmentから参照されるため、ここでは直接取得しないことが多い
}
class ChildFragmentA : Fragment() {
// 親ActivityのViewModelを共有
private val sharedViewModel: SharedViewModel by activityViewModels()
// ...
}
class ChildFragmentB : Fragment() {
// 親ActivityのViewModelを共有
private val sharedViewModel: SharedViewModel by activityViewModels()
// ...
}
by navGraphViewModels()
スコープ
ライフサイクル
指定したナビゲーショングラフがバックスタックに存在する間、ViewModelは生存し続けます。ナビゲーショングラフがバックスタックから削除されると、対応するViewModelも破棄されます。
使い方
by navGraphViewModels(<ナビゲーションID>) のように、Navigationコンポーネントを使用している場合に、特定のナビゲーショングラフ内の複数のFragment間でデータを共有したいときに使用します。
例えば、ユーザー登録フローのように、いくつかの画面(Fragment)にまたがる一連の操作で共通のデータが必要な場合に非常に有効です。
// navigation/nav_graph.xml で定義されたナビゲーショングラフのIDを使用
class StepOneFragment : Fragment() {
private val navGraphViewModel: RegistrationViewModel by navGraphViewModels(R.id.registration_nav_graph) // ナビゲーショングラフIDを指定
// ...
}
class StepTwoFragment : Fragment() {
private val navGraphViewModel: RegistrationViewModel by navGraphViewModels(R.id.registration_nav_graph) // ナビゲーショングラフIDを指定
// ...
}
まとめ
ここまで見てきたように、適切な by 委譲プロパティを選択することは、アプリケーションのデータの整合性を保ちながら、ViewModelのスコープとライフサイクルを効率的に管理するために非常に重要です。これらのデリゲートを適切に使い分けることで、より堅牢でメンテナンス性の高いAndroidアプリケーション開発を実現できます。

