デザインパターンDIとDaggerを使ったAndroid開発(2)

初めに

(✿✪‿✪。)ノコンニチワ♡ OWNR by RENOSY Android開発のSugeunです。 前回デザインパターンDIとDaggerを使ったAndroid開発(1)編ではDaggerとDIはなんなのかについて簡略に説明しました。今回も引き続きDaggerをもっと深めたいと思います。 OWNR by RENOSYはDIパタンとDaggerを採択したアプリとして不動産投資を行なっているオーナーさんにもっと物件管理をし易く助けてくれる不動産オーナー向けのアプリケーションです。 今回3.9.0アップデートで源泉徴収票機能が追加されたので、ぜひ使ってみてください。

www.renosy.com

Singletonアノテーション

プログラミングでスコープと言うものは変数や関数などが共有や参照できる範囲を意味します。 大きくどこでも使われるGlobal Scopeと指定した範囲内のみ使うことができるLocal Scopeに分かれます。Daggerにももっと効果的に使えることを助けるSingletonスコープ存在します。

ModuleとComponentが依存性を注入対象間の契約関係をDagger Graphと言います。そのDagger Graph内部にあるオブジェクトを@Singletonを使うことでオブジェクトの再使用を指定することができます。

使う方法としてはmoduleクラスから@Providesメソッドと@Inject可能なクラスに@Singletonを付けてください。

@Module
class ExampleModule{
    @Singleton
    @Provides
    fun exampleProvidesOne() : Hoge { 
        return Hoge()
    }
    @Singleton
    @Provides
    fun exampleProvidesTwo(somethingRepository : SomethingRepository) : Fuga() {
        return Fuga(somethingRepository)
    }
}

*注意:@SingletonはModuleとComponent二つの場所で付ける必要があります! Componentにも@Singletonを付けてあげましょう。

@Singleton
@Component(
    modules = { ExampleModule::class,SomethingModule::class }
)

interface ExampleComponent {
    @Component.Builder
    interface Builder {
        @BindsInstacne
        fun application(application : Application) : Builder        
    }
}

@Singletonを使うことで、Componentの内部でScopeを管理することにより、最初要望だけオブジェクトを生成して、その次の注入要望では最初作ったオブジェクトのインスタンスを提供してくれます。

多様なInjections

OWNR by RENOSY では@Injectionを使っていますが、この度、Daggerを学び始めて色々な種類のInjectionがあることをわかるようになりました。 Injectionは大きく三つの種類に分けます。

  • Direct Injections

一般的に使われるInjectionです。最初注入して貰ったオブジェクトを後で注入しても同じオブジェクトを注入します。

    @Inject
    var AnnualIncomeAmount: AnnualIncomeModel? = null
  • Lazy Injections

オブジェクトを初期化するための時間が使われるInjectionです。この場合タイプの指定をLazyタイプに宣言する必要があります。必要な瞬間まで最大限初期化を遅延します。 これはKotlinの初期化遅延プロパティkotlin leteinitと似ているイメージです。

    @Inject
    var AnnualIncomeAmount: Lazy<AnnualIncomeModel>? = null
  • Provider Injections

普通のDirect Injectionsとは違って注入されると新しいオブジェクトをインスタンス化して注入されます。@Injectの役割はちゃんと行われていますけど、@Providesは行っていないイメージです。

    @Inject
    var AnnualIncomeAmount: Provider? = null

*注意:Providers InjectionsはDagger Graph内で間違っているScopeや設計パタンを作られる恐れがあるので、使う場合は気を付けてください。

易しいテスト

皆様はPresenterのTest Codeを書いた経験がございますか。

DI Frameworkを使っているのでテストFileの中で使われるインスタンスに対してインスタンス化を外部から行います。それにMockito*1を一緒に使うことで既存のテストより楽になります。😇

Testの中でUse CaseとRepositoryを使ってテストを行うところで、実際にRoomの変更が行う場合にはDaggerからFake Compponentを通じて変わったRoomのデータでテストが可能になります。Daggerが無かったら自らMock化したインスタンスを最新化して直接注入する必要があることです。

最後に

今行なっているプロジェクトが小規模とか、データの更新や使用が少ないプロジェクトはわざわざDaggerを使う必要はないですが、どんどんプロジェクトの規模を増やしたい場合等はぜひDaggerの採択をご検討してください。

今回も読みいただきありがとうございました。(✿✪‿✪。)ノ🌸

*1:単位テストのためのJava Mocking Frameworkを言います。@Mockを付けることでmockオブジェクト(中は空)を作って返してくれます。