Koinとは
タイトルにモロに書いてありますが、
A pragmatic lightweight dependency injection framework for Kotlin developers.
Kotlin開発者向けの実用的な軽量のDI(依存性注入)フレームワーク
です。
Daggerと比べてわかりやすいと感じたので、備忘録のために使い方をまとめます。
使い方(3ステップ)
1. Moduleを宣言する
// いくつかのクラスがあるとします。
class Controller(val service : BusinessService)
class BusinessService()
class MyViewModel(context: Application) : AndroidViewModel(context)
// DSLでそれらを指定してモジュール宣言をするだけです。
val myModule = module {
factory { Controller(get()) }
single { BusinessService() }
viewModel { MyViewModel(androidContext() as Application) }
}
module
や factory
などの書き方はDSLですので、詳しくはこちらを参照してください。
コンストラクタがある場合は、get()
を使用します。
注入したいクラスをSingletonにしたい場合はsingle
を使用します。
また、ViewModelの宣言はDSLでviewModel
と指定できます。このとき、Activity-Fragment間でViewModelを共有したいときに用いるAndroidViewModel
を継承しているViewModelの場合はコンストラクタにApplicationを持っているので、get()
でもいいですが、androidContext() as Application
でも取得できるらしいので、こちらを使っておきます。
モジュールを宣言する場所は、例えば、di
などのパッケージを切って、その中にmyModule
などのファイルを作成してその中でトップレベルプロパティとして宣言するのが良いかと。
2. Koinを開始する
class MyApplication : Application() {
override fun onCreate(){
super.onCreate()
// `startKoin` でKoinを開始します。
startKoin {
// Contextを宣言し、
androidContext(this@MyApplication)
// 先ほど宣言したmoduleを指定します。
modules(myModule)
}
}
}
Applicationクラスを継承したクラス内で色々と宣言して startKoin
するだけです。
3. インスタンスを注入する
// あとは、Activity内でインスタンスを注入するだけです。
class MyActivity() : AppCompatActivity() {
// serviceプロパティの中へBusinessServiceを遅延注入する。
val service : BusinessService by inject()
val viewModel: MyViewModel by viewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// もしくは、直接インスタンスを取得する。
val service : BusinessService = get()
}
}
最後は、 by inject()
でインスタンスを注入するだけです。
そのプロパティが初めて呼ばれたときに注入しています。
もしくは、get()
でも取得可能なのですね。(知らなかった)
viewModelを注入したいときは、by viewModel()
を使用します。
DI前だったら
lateinit var vm: MyVeiwModel
からの
vm = ViewModelProviders.of(this).get(MyViewModel::class.java)
とかわんさかコード書かないといけなかったから、これがなくなるのは助かる。
Activity, Fragment, Service以外のクラスで注入したい場合は、KoinComponent
インターフェースを実装すれば、注入できるようになります(by inject()
が使用できるようになります)
終わりに
Koin万歳!!!
Daggerも慣れてしまえば問題ないですが、Koinより学習コストが高めなので(私の理解力の問題かも...)、Daggerを使用しなければならない場合以外は、Koin使いたいなぁ。
※追記
と思っていましたが、シニアエンジニアの方にKoinは動作が遅いということをお聞きし、調べてみました。次のサイトで様々なDIフレームワークでのパフォーマンスを調べてくれてました。
https://github.com/Sloy/android-dependency-injection-performance
Dagger2めちゃくちゃ早くて驚いた。。。
これは学習コスト云々以前に、一人のエンジニアとして品質の面でDaggerを使うべきだなと感じさせられました。
参考(というか公式)