はじめに
この記事は、developer.android.comのHilt を使用した依存関係の注入を参照してのセットアップになります。
developer.android.comの内容は古いので、daggerの公式も参照してください。
概要
AndroidでHiltを使おうと、Hilt を使用した依存関係の注入 を参照したら、ドキュメントが古いためエラいハマったので、New Project→Basic Activityから最速でHiltをセットアップするための手順書になります。
特に言及のないところは公式ドキュメント通りで大丈夫かと思います。
環境
- Android Studio
- 4.2.2
- 言語
- Kotlin
依存関係を追加する
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
ではなく、classpath 'com.google.dagger:hilt-android-gradle-plugin:2.37'
を追加します。
kotlin_versionも、1.5.20にすると以下のようなエラーに悩まされるので、1.5.10にします。
public final class MainActivity extends androidx.appcompat.app.AppCompatActivity {
^
Expected @AndroidEntryPoint to have a value. Did you forget to apply the Gradle Plugin? (dagger.hilt.android.plugin)
See https://dagger.dev/hilt/gradle-setup.html
[Hilt] Processing did not complete. See error above for details.
プロジェクトのルート build.gradle ファイル
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.10"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.37'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
app/build.gradle ファイルも、com.google.daggerの各種バージョンを2.37にして追加します。
プラグインの書き方はapply
ではなくplugins
に列挙する形になっているので、その形式に合わせます。
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
// Hilt
implementation "com.google.dagger:hilt-android:2.37"
kapt "com.google.dagger:hilt-android-compiler:2.37"
}
Hilt アプリケーション クラス
New→Kotlin Class/Fileでファイルを追加します。
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class ExampleApplication: Application() {
}
AndroidManifest.xmlにもapplication要素にandroid:nameを追加するように編集します。
<application
android:name=".ExampleApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplicationHilt">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.MyApplicationHilt.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Android クラスに依存関係を注入する
公式ドキュメントでは、ExampleActivityを作成していますが、以下は最初からあるMainActivityに実装する例です。
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var analytics: AnalyticsAdapter
Hilt バインディングを定義する
New→Kotlin Class/FileでAnalyticsAdapterファイルを追加します。
import javax.inject.Inject
class AnalyticsAdapter @Inject constructor(
private val service: AnalyticsService
) {
}
Hilt モジュール
@Binds を使用してインターフェース インスタンスを注入する
New→Kotlin Class/FileでAnalyticsServiceファイルを追加します。
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import javax.inject.Inject
interface AnalyticsService {
fun analyticsMethods()
}
// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl @Inject constructor(
) : AnalyticsService {
override fun analyticsMethods() {
TODO("Not yet implemented")
}
}
@Module
@InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {
@Binds
abstract fun bindAnalyticsService(
analyticsServiceImpl: AnalyticsServiceImpl
): AnalyticsService
}
以上でビルドが通り、MainActivityからAnalyticsAdapterとAnalyticsServiceが利用できるようになるかと思います。
Hilt と Jetpack の統合(ViewModel & Fragment)
Hilt と Jetpack の統合もドキュメントが古いので、こちらも2021/07現在の環境でセットアップします。
以下はFragmentに対してのViewModelでのセットアップになります。
Hilt を使用して ViewModel オブジェクトを注入する
まずは、New→Fragment→Fragment (With ViewModel)で ExampleFragment
を作っておきます。
app/build.gradleファイルは、
-
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
→implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
-
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
→kapt 'androidx.hilt:hilt-compiler:1.0.0'
にします。
dependencies {
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
// When using Kotlin.
kapt 'androidx.hilt:hilt-compiler:1.0.0'
}
ViewModelInjectはHiltViewModel
に置き換えられているので、置き換えます。
ExampleRepositoryがconstructorに必要なので用意しておきます。
ExampleRepositoryの中身の例です。
import javax.inject.Inject
class ExampleRepository @Inject constructor() {
fun get(): String {
return "get"
}
}
ViewModelの例です。
@HiltViewModel
class ExampleViewModel @Inject constructor(
private val repository: ExampleRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = repository.get()
}
val text: LiveData<String> = _text
}
そのViewModelを使うFragmentの例です。
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class ExampleFragment : Fragment() {
companion object {
fun newInstance() = ExampleFragment()
}
private val viewModel: ExampleViewModel by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
viewModel.text.observe(viewLifecycleOwner, Observer {
Log.d("ExampleFragment",it)
})
return inflater.inflate(R.layout.example_fragment, container, false)
}
}
以上、駆け足ですが、2021/07時点でのAndroid Hiltセットアップの例でした。