Hilt利用の基本
プロジェクトの準備ができたので、実際にHiltを利用していきましょう。
アプリケーションクラスの作成
Hiltを利用する場合、何はともあれ、Androidのアプリケーションクラスを作成し、そこにアノテーションを付与する必要があります。
アプリケーションクラスは、その名称の通り、Androidアプリ本体を表すクラスです。アプリが起動した際にまずインスタンス化されるのがこのクラスです。通常は、SDKに含まれているApplicationクラスが利用されますが、今回のようにカスタマイズの必要がある場合は、Applicationクラスを継承して独自クラスとします。
これは、Javaならばリスト5、Kotlinならばリスト6のコードです。
@HiltAndroidApp
public class HiltSampleApplication extends Application {}
@HiltAndroidApp
class HiltSampleApplication : Application() {}
ここでのポイントは、@HiltAndroidAppアノテーションです。これを記述し忘れるとHiltが動作しません。
なお、ここでは、クラス名としてHiltSampleApplicationとしていますが、Applicationクラスを継承していれば、クラス名はなんでもかまいません。ただし、このクラスを、アプリケーションクラスとして利用するように、AndroidManifest.xmlに登録する必要があります。これは、リスト7のように、applicationタグのname属性の追記です。
<manifest …>
<application
android:name=".HiltSampleApplication"
:
</application>
</manifest>
エントリポイントの設定
Hiltを利用する場合、もうひとつ大切なコードがあります。それは、DIの開始点(=エントリポイント)に@AndroidEntryPointアノテーションを付与することです。
今回で言えば、これは、MainActivityになるので、Javaならばリスト8、Kotlinならばリスト9のコードとなります。
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
:
}
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
:
}
コンストラクタインジェクション
準備が整ったところで、シンプルな例として、図4のViewModel内でリポジトリを利用する例でHiltの利用方法を紹介します。
ここでのViewModelをMainViewModel、リポジトリをMemoRepositoryとします。すると、Javaコードでは、MainViewModelはリスト10のコード、MemoRepositoryはリスト11のコードとなります。
public class MainViewModel extends ViewModel {
private final MemoRepository _memoRepository; // (1)
:
@Inject // (2)
public MainViewModel(MemoRepository memoRepository) { // (3)
_memoRepository = memoRepository; // (4)
}
:
}
public class MemoRepository {
@Inject // (1)
public MemoRepository() {
:
}
:
}
ポイントは、次の2点です。
両クラスともにコンストラクタに@Injectアノテーションを付与する。
リスト10の(2)、および、リスト11の(1)が該当します。コンストラクタの処理が不要でも、アノテーションのためにコンストラクタを実装します。
依存インスタンスをコンストラクタで受け取るようにする。
ここでの例では、MainViewModelがMemoRepositoryに依存します。その場合、MainViewModel内でMemoRepositoryをnewするのではなく、リスト10の(3)のように、コンストラクタの引数として定義します。これだけで、Hiltにより、自動的にMainViewModelインスタンスが生成される際に、MemoRepositoryインスタンスが渡されるようになります。ただし、このインスタンスをクラス内で利用できるように、(1)のようなフィールドを用意し、(4)のようにコンストラクタ内でフィールドに格納するコードは、もちろん必要です。
このように、コンストラクタで依存先インスタンスを受け取る仕組みを、コンストラクタインジェクション(Constructor Injection)といいます。
Kotlinコードの場合も同じであり、MainViewModelはリスト12、MemoRepositoryはリスト13となります。完全にJavaコードを置き換えた内容です。ただし、コンストラクタにアノテーションを付与する関係上、constructorキーワードは省略できません。
class MainViewModel
@Inject
constructor(
private val _memoRepository: MemoRepository
) : ViewModel() {
:
}
class MemoRepository @Inject constructor() {
:
}
まとめ
Android Jetpackについて紹介していく本連載の第17回は、いかがでしたでしょうか。
今回は、Android開発でDI(Dependency Injection)を実現するHiltを紹介しました。
長らく続いた本連載も、次回で最終回です。その最終回である次回も、Hiltを紹介します。具体的には、コンストラクタインジェクション以外の注入の方法、モジュールの利用を紹介します。
