MVVM で Hilt のパターン化 💉

シンプルなものにして整理、定型化しておきたい。

「どこに」←「どれを」インジェクトしてるか、とそれの記述をパターン化。

 

💉 View ← ViewModel

MVVM でいうところの View であるこれらに、ViewModel をインジェクトする場合。

コンストラクタからインジェクトできないいわゆる「Androidクラス」。
以下のものがこれに当てはまる。

- Activity
- Fragment
- View
- Service
- BroadcastReceiver

それぞれのクラスに付ける2つのアノテーションと ktx による記述でプロパティにインジェクトする。


@AndroidEntryPoint
class MainFragment : Fragment() {
  private val viewModel: MainViewModel by viewModels()


@HiltViewModel
class MainViewModel @Inject constructor(
  repository: MainRepository
) : ViewModel() {

 


💉 ViewModel ← Repository

Module を使った ViewModel コンストラクタへのインジェクト。

インターフェースの型でリンクする。


@HiltViewModel
class MainViewModel @Inject constructor(
  repository: MainRepository
) : ViewModel() {

Hilt 備え付けの Component でライフサイクルを考慮して、実装型でインジェクトする。

abstract、@Binds は、インターフェースを介す場合の、 @InstallIn( ViewModelComponent::class)、 @ViewModelScoped は、 ViewModel に対してのインジェクトのパターン。


@Module
@InstallIn(ViewModelComponent::class)
abstract class RepositoryModule {

  @Binds
  @ViewModelScoped
  abstract fun bindRepository(impl: DefaultRepository): MainRepository
}

 

💉 Repository ← DataSource

Androidクラスのようなプロパティへのインジェクトとは違う @Module、@Provides を使ったコンストラクタインジェクトの Hilt基本的パターン。

SingletonComponent は、旧 ApplcationComponent で生存期間最長。


class DefaultRepository @Inject constructor(
  private val localDao: LocalDao,
  private val contentResolver: ContentResolver,
  private val sharedPreferences: SharedPreferences
) : MainRepository {


@Module
@InstallIn(SingletonComponent::class)
object DataSourceModule {

  @Provides
  @Singleton
  fun provideLocalDao(
    @ApplicationContext context: Context
  ): LocalDao {
    return LocalDao(context)
  }

 

💉 DataSource ← Context

Context は、 @ApplicationContext と @ActivityContext がすでに用意されているので区別しながらアノテーション1つのみで注入できる。これ便利。


@Module
@InstallIn(SingletonComponent::class)
object DataSourceModule {

  @Provides
  @Singleton
  fun provideLocalDao(
    @ApplicationContext context: Context
  ): LocalDao {
    return LocalDao(context)
  }

しかし、どの位置でも自在にインジェクトしようとするとコケる。


[Dagger/MissingBinding] @dagger.hilt.android.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method.

@Module 直下の @Provides メソッドの引数で使うものですか。

 

build.gradle


buildscript {
  ext.versions = [
    "hilt"       : "2.41",
  ]
  dependencies {
    classpath "com.google.dagger:hilt-android-gradle-plugin:${versions.hilt}"
  }
}

apply plugin: "org.jetbrains.kotlin.kapt"
apply plugin: "dagger.hilt.android.plugin"

dependencies {
  implementation "com.google.dagger:hilt-android:${versions.hilt}"
  kapt "com.google.dagger:hilt-android-compiler:${versions.hilt}"

  androidTestImplementation  "com.google.dagger:hilt-android-testing:${versions.hilt}"
  kaptAndroidTest "com.google.dagger:hilt-compiler:${versions.hilt}"
  testImplementation "com.google.dagger:hilt-android-testing:${versions.hilt}"
  kaptTest "com.google.dagger:hilt-compiler:${versions.hilt}"
}

👉 Gradle Build Setup 

 

💉 まとめ

多少の流儀はあるけど、 Component 記述がなくなっただけでも記述量は大幅に削減できます。

alpha らしく、まだコンポーネント名など変わるんかもしれんが、ここも適宜修正させてもらいます。

👉 【MVVM】 Kotlin Flow で使える5つの利用パターン 
👉 skydoves/Pokedex: 🗡️ Android Pokedex using Hilt, Motion, Coroutines, Flow, Jetpack (Room, ViewModel) based on MVVM architecture. 
👉 Hilt and Dagger annotations cheat sheet - Android Developers - Medium 



画面上部のLED点滅は一体なんだったのか【Android12 / Pixel5】

ロック画面時に謎だったのですが、



このアプリを入れてみて分かりました。

👉 センサーツールボックス - Google Play のアプリ 



「近接センサー稼働中」

の明示ですね。

で、

ロック画面では、どの機能がLEDを点滅させているか?

ということですが、

How to disable the annoying flashing dot on your Pixel 5

[設定] - [システム] - [ジェスチャー] からの

「ふせるだけでサイレントモードをオン」

のようです。

👉 How to disable the annoying flashing dot on your Pixel 5 - 9to5Google 


Mac に Homebrew で OpenJDK11 を インストール する

http://openjdk.java.net/


➜  ~ brew search openjdk
==> Formulae
openjdk         openjdk@11     openjdk@8       openj9          openvdb

...

openjdk@11 — Homebrew Formulae
👉 openjdk@11 — Homebrew Formulae 


➜  ~ brew info openjdk@11
openjdk@11: stable 11.0.12 (bottled) [keg-only]
Development kit for the Java programming language
https://openjdk.java.net/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openjdk@11.rb
License: GPL-2.0-only
==> Dependencies
Build: autoconf ✔
==> Caveats
For the system Java wrappers to find this JDK, symlink it with
  sudo ln -sfn /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk

openjdk@11 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have openjdk@11 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openjdk@11/bin:$PATH"' >> ~/.zshrc

For compilers to find openjdk@11 you may need to set:
  export CPPFLAGS="-I/usr/local/opt/openjdk@11/include"

...


➜  ~ brew install openjdk@11
...

「keg-only」は「リンクされていない」。


➜  ~ sudo ln -sfn /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk
➜  ~ echo 'export PATH="/usr/local/opt/openjdk@11/bin:$PATH"' >> ~/.zshrc
➜  ~ export CPPFLAGS="-I/usr/local/opt/openjdk@11/include"


➜  ~ vi .zshrc                                                                      
...
#export PATH="/usr/local/opt/openjdk@11/bin:$PATH"

JAVA_8_HOME=$(/usr/libexec/java_home -v1.8)
JAVA_11_HOME=$(/usr/libexec/java_home -v11)

export JAVA_HOME=$JAVA_11_HOME
export PATH="$JAVA_HOME/bin:$PATH"


➜  ~ source ~/.zshrc


➜  ~ ls -l /Library/Java/JavaVirtualMachines
total 0
drwxr-xr-x  3 root  wheel  96 11 10  2020 adoptopenjdk-8.jdk
lrwxr-xr-x  1 root  wheel  45 11 30 09:43 openjdk-11.jdk -> /usr/local/opt/openjdk@11/libexec/openjdk.jdk


➜  ~ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    11.0.12 (x86_64) "Homebrew" - "OpenJDK 11.0.12" /usr/local/Cellar/openjdk@11/11.0.12/libexec/openjdk.jdk/Contents/Home
    1.8.0_275 (x86_64) "AdoptOpenJDK" - "AdoptOpenJDK 8" /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
/usr/local/Cellar/openjdk@11/11.0.12/libexec/openjdk.jdk/Contents/Home


➜  ~ java -version
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment Homebrew (build 11.0.12+0)
OpenJDK 64-Bit Server VM Homebrew (build 11.0.12+0, mixed mode)


➜  ~ javac -version
javac 11.0.12


👉 OpenJDK 
👉 AdoptOpenJDK - Open source, prebuilt OpenJDK binaries 
👉 Adoptium - Open source, prebuilt OpenJDK binaries 

👉 KMM まとめ 速報 - Kotlin Multiplatform Mobile 【#ios | #android】 

👉 MacでインストールされているJavaを確認する方法 - Qiita 
👉 Homebrewでjavaをインストールする方法 - Qiita 
👉 MacにJava開発環境をインストールする - Qiita