インジェクションの別パターン
本連載は、Android Jetpackを紹介しています。長らく続いた本連載も、今回が最終回です。
前回、HiltによるDIの方法としてコンストラクタインジェクションを紹介しました。そのコンストラクタインジェクションが、HiltによるDIの基本です。
今回は、この基本では対応できないパターンを2個紹介することから始めていきます。
なお、今回のサンプルデータはGitHubから参照できます。
フィールドインジェクション
まず、コンストラクタを独自定義できないクラスの場合についてです。アクティビティはその典型です。そこで、前回の図1のパターンからは外れますが、アクティビティからリポジトリを直接利用する場合のインジェクションのコードを紹介します。
これは、Javaではリスト1、Kotlinではリスト2のコードとなります。
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
@Inject
MemoRepository _memoRepository;
:
}
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var _memoRepository: MemoRepository
:
}
ここでのポイントは、フィールド/プロパティに@Injectアノテーションを付与することです。この仕組みを、フィールドインジェクション(Field Injection)と言います。
ただし、該当フィールド/プロパティは、privateにしてはいけません。なぜならprivateだと外部から注入できなくなってしまうからです。また、Kotlinの場合はlateinit varとなります。
ViewModelのインジェクション
次に、ViewModelのインジェクションです。前回の図1のパターンに話を戻すと、アクティビティ/フラグメントは、ViewModelに依存します。
しかし、そもそもViewModelは直接newするわけではありません。JavaならばViewModelProviderによる生成コード、Kotlinならばby viewModels()による委譲プロパティとして生成します。
そこで、ViewModelに関してはアクティビティ/フラグメント側での生成コードはそのままとして、ViewModelクラスに@HiltViewModelアノテーションを付与するだけで、問題なく注入されるようになります。
そのため、Javaならばリスト3、Kotlinならばリスト4のコードとなります。
@HiltViewModel
public class MainViewModel extends ViewModel {
:
@Inject
public MainViewModel(…) {
:
}
:
}
@HiltViewModel
class MainViewModel
@Inject
constructor(…) : ViewModel() {
:
}
