#この記事について
MVVMでのAndroidのDIライブラリであるHiltの使い方を、同じJetpackライブラリであるRoomを用いて解説します。
今回はRoomの構築部分は割愛します。
#Hiltの依存関係を追加
まずは、Hiltプラグインをプロジェクトのルートに追加します。
buildscript {
...
dependencies {
...
def hilt_version = '2.33-beta'
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}
次に、app/build.gradleファイルに依存関係を追加します。
plugins {
...
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
def hilt_version = "2.33-beta"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
}
Java8を有効にするには、同じくapp/build.gradleに以下を追加
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
#ApplicationクラスにHiltを導入
Applicationを継承した自作のApplicationクラスに**@HiltAndroidApp**をつけます。
@HiltAndroidApp
class MyApplication : Application() { ... }
作成したMyApplicationをAndroidManifest.xmlに追記します。
<application
android:name="(プロジェクト名).MyApplication"
これにより、HiltコンポーネントはApplication オブジェクトのライフサイクルにアタッチされ、依存関係を提供します。
Applicationはアプリの親コンポーネントであることから、他のコンポーネントが依存関係にアクセスできるようになります。
#Androidクラスに依存関係を注入する
Application クラスで Hilt がセットアップされ、アプリケーションレベルのコンポーネントが利用可能になると、@AndroidEntryPoint アノテーションが付けられた他の Android クラスに依存関係を提供できるようになります。
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {...}
Fragmentを利用する際も同様に**@AndroidEntryPoint**をつけます。
@AndroidEntryPoint
class MyFragment : Fragment() {...}
※Fragmentの親となるActivityにも@AndroidEntryPointを設置することを忘れないように!!
#Hiltを使ってViewModelオブジェクトを注入する
次に、ActivityやFragmentと紐づいているViewModelに依存関係を注入していきます。ViewModelには**@HiltViewModelをつけます。
また、このときにViewModelからRepositoryを参照・使用するために依存関係を注入していきますが、この方法としては@Inject**を使った以下の2つがあります。
・Constructor Injection
・Field Injection
以上2つの注入の仕方について説明します。
##Constructor Injection
@HiltViewModel
class MyViewModel @Inject constructor(
private val repository: MyRepository
): ViewModel() {...}
本記事ではこの後、Constructor Injectionを使っていきます。
##Field Injection
@HiltViewModel
class MyViewModel(): ViewModel() {
@Inject lateinit var repository: MyRepository
}
#RepositoryにRoom Daoを注入
続いてRepositoryをみていきましょう。
ここではRoomのDaoをRepositoryに注入し、Daoにあるメソッドを呼び出します。注入の仕方は前述のViewModelと同じ**@Inject**で注入できます。
class MyRepository @Inject constructor(private val myDao: MyDao) {...}
これでRepositoryからMyDaoを呼び出すことが可能になります。
例えばMyDao内でSELECTしてきた次のようなデータを
@Dao
interface MyDao {
@Query("SELECT * FROM user")
fun findAll(): List<User>
}
Repositoryからは
class MyRepository @Inject constructor(private val myDao: MyDao) {
fun findAllInDB() = myDao.findAll()
}
これで呼び出し完了です!!
##Hiltモジュールの作成
Hiltモジュールでは**@Module**をつけたクラスから、特定の型のインスタンスの提供方法を Hilt に知らせることができます。
ここではRoom Databaseの構築と、Daoの実装を行います。
@Module
@InstallIn(SingletonComponent::class)
object MyModule {
@Singleton
@Provides
fun provideDatabase(
@ApplicationContext context: Context
) = Room.databaseBuilder(context, AppDatabase::class.java, "user_db").build()
@Singleton
@Provides
fun provideDao(db: AppDatabase) = db.myDao()
}
・@InstallIn:各モジュールが使用またはインストールされる Android クラスを知らせます。ここではSingletonComponentを用いることで、アプリケーション内のどこからでもアクセス可能になります。その他のComponentについてはAndroid Developersをご覧ください。
・@Singleton:同じインスタンスを使いまわすことができます。このアノテーションを外すと、依存注入のたびに新しいインスタンスが生成されます。
・@Provides:このアノテーションをつけた関数のインスタンスを提供します。Room等のDBのほか、RetrofitやOkHttpClientのBuildでインスタンスを生成するときも同様です。
とりあえずはこれでHiltを使ったRoomの依存関係注入は完了です!
同じようにHilt + Roomを使ったアプリをGitHubで公開しているので、こちらもご覧ください。
GitHub
#参考記事
Hilt and Jetpack integrations
Dependency injection with Hilt
How to create and use a Room Database in Kotlin [Dagger-Hilt]