実用的な Kotlin および Kotlin マルチプラットフォーム依存関係注入フレームワーク
実用的な Kotlin および Kotlin マルチプラットフォーム依存関係注入フレームワーク
Android Studio 環境は Android Studio Flamingo | 2022.2.1です。
Koinの最新バージョンは3.4.0です。
Koin は、Android アプリケーションがコンポーネント間の依存関係を簡単に管理できるようにする軽量の依存関係注入フレームワークです。
Koin の主な目標は、依存関係の注入をシンプルにし、理解しやすく、使いやすくすることです。コード生成やリフレクションを行わず、純粋な Kotlin で記述されていますが、機能的な DSL とアノテーションに基づいており、依存関係を宣言および管理するためのシンプルかつ強力な方法を提供します。
依存関係を追加する
dependencies {
def koin = "3.4.0"
implementation("io.insert-koin:koin-core:$koin")
implementation("io.insert-koin:koin-android:$koin")
implementation("io.insert-koin:koin-android-compat:$koin")
}
core
Koinのコアについて-android
Android向けKoinが提供する拡張メソッドの一部です-compat
Androidコンポーネント向けにKoinが提供するいくつかの拡張メソッドです
Koinは上記3つに加えて、composeやktorにも対応しており、Android側でもサーバー側でも依存関係注入にKoinを利用できると言えますが、Hiltとの違いはKoinがkotlin環境で利用される点です。
使い始める
class KoinApp : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidLogger()
androidContext(this@KoinApp)
modules(normalModule)
}
}
}
startkoin{}
Koin機能をオンにし、いくつかの設定を行います
androidLogger()
Koinの実行ログを開くandroidContext()
バインディングApplication
コンテキスト。後でKoinから直接取得できます。module()
Koinに渡されるモジュール。このモジュールは私たちが定義した依存性注入アイテムです。
Koinを使用してオブジェクトを注入する
まず、Koin を使用して通常のオブジェクトとシングルトン オブジェクトを注入してみましょう. オブジェクトの構築メソッドの前にアノテーションを追加する必要はなく、侵入することなく元のコードで使用できるため、以前のコードで Koin を変更することができます. Koin がどのようにオブジェクトを注入するかを見てみましょう
// 定义两个对象,分别用来演示常规的对象和单例对象注入
class KoinTest {
fun test() {
Log.d(TAG, "KoinTest test $this")
}
}
class SingletonTest {
fun test() {
Log.d(TAG, "SingletonTest test $this")
}
}
// normalMoudle就是来管理常规的对象注入
val normalModule = module {
factory {
KoinTest() }
}
// singleModule则是用来单例对象注入
val singleModule = module {
single {
SingletonTest() }
}
val moduleList = listOf(normalModule, singleModule)
startKoin {
androidLogger(Level.DEBUG)
androidContext(this@KoinApp)
// 将moduleList传入modules中,这样Koin就会帮助我们实现依赖注入
modules(moduleList)
}
上記のコードは依存性注入の実装に役立ち、注入されたオブジェクトを使用するときにby inject()
Koin の拡張メソッドを直接使用して対応するインスタンスを取得できます。
class MainActivity : BaseActivity<ActivityMainBinding>() {
// 使用Koin进行对象注入
private val koinTest: KoinTest by inject()
private val singletonTest: SingletonTest by inject()
override fun initViewBinding(): ActivityMainBinding {
return ActivityMainBinding.inflate(layoutInflater)
}
override fun onResume() {
super.onResume()
koinTest.test()
singletonTest.test()
}
}
# log
KoinTest test com.example.koin.KoinTest@e0d5daf
SingletonTest test com.example.koin.SingletonTest@29665bc
ログ内のオブジェクトに注目してください。インジェクションにKoinTest
使用するとfactory{}
、インジェクションするたびに新しいオブジェクトが生成されます。インジェクションにSingletonTest
使用するとsingle{}
、オブジェクトは毎回変更されませんActivity
。
class SecActivity:BaseActivity<ActSecBinding>() {
private val koinTest: KoinTest by inject()
private val singletonTest: SingletonTest by inject()
override fun initViewBinding(): ActSecBinding {
return ActSecBinding.inflate(layoutInflater)
}
override fun onResume() {
super.onResume()
koinTest.test()
singletonTest.test()
}
}
# log
KoinTest test com.example.koin.KoinTest@17dbb11
SingletonTest test com.example.koin.SingletonTest@29665bc
KoinTest
ログから、それが実際に新しいオブジェクトであり、SingletonTest
以前に挿入されたオブジェクトと同じであることがわかります。そのため、Koin を使用してさまざまな種類のオブジェクトの挿入を完了することができます。
Koin は注入するだけでなくby inject()
、直接get()
オブジェクトを注入することもできます。両者の違いは、1 つは遅延読み込みモード、もう 1 つは直接取得モードであることです。
inject()
返されるのはオブジェクトですが、メソッドはLazy
引き続き内部で呼び出されます。get()
get()
注入する必要があるオブジェクト インスタンスを返します。
日々の使用用途に合わせてお選びください。
Hilt と比較して、Koin を使用して依存性注入を実装する方が便利だと思いますか? 確かに、記述の利便性は向上しますが、Koin と Hilt にはそれぞれ長所と短所があります。詳細については、次の記事で紹介します。
KoinでのApplicationContextの使用
androidContext()
Koinを開くときは、渡されたオブジェクトを使用しますApplication
。これにより、Application
後で使用する必要があるときにパラメータを渡す必要がなく、get()
Koinから直接取得できるという利便性が得られます。
class ContextTest(
private val context: Application
) {
fun test() {
Log.d(TAG, "ContextTest test: ${context.getString(R.string.app_name)}")
}
}
val normalModule = module {
// 这里直接使用get()来注入context对象
factory {
ContextTest(get()) }
}
# log
ContextTest test: koin
KoinでのViewModelの使用
Koin にオブジェクトを注入する場合ViewModel
、大きく分けて 2 つのタイプに分けられます。1 つはパラメータなしのタイプです。Koin をViewModel
使用しない場合は、activity-ktx
拡張ライブラリを直接使用してオブジェクトby viewModels()
を取得ViewModel
できます。確かに Koin よりも簡単ですが、2 つ目のパラメータ付きのタイプでは、Koin の記述が若干有利です。以下、2ViewModel
つの記述方法を詳しく見て、Koin の魅力をコードレベルから直感的に感じてみましょう。
パラメータ ViewModel を挿入しません
// 定义一个无参的ViewModel
class KoinViewModel : ViewModel() {
fun test() {
Log.d(TAG, "KoinViewModel test")
}
}
val viewModelModule = module {
// 使用Koin的viewModel{}来注入KoinViewModel对象
viewModel {
KoinViewModel() }
}
// 在Activity中使用 by viewModel() 懒加载来获取KoinViewModel对象
private val koinViewModel: KoinViewModel by viewModel()
koinViewModel.test()
# log
KoinViewModel test
ViewModel
この特別なオブジェクトに対応して、Koin は、このオブジェクトを簡単に注入し、viewModel{}
使用時に拡張メソッドを通じてby viewModel()
対応するオブジェクトを直接取得するのに役立つ方法を提供します。その内部実装は、対応するオブジェクトを作成するためにViewModel
通常使用されるものです。Koin は、 から継承されたone を内部的にカプセル化します。ViewModelProvider
ViewModel
KoinViewModelFactory
ViewModelProvider.Factory
ViewModel を参照とともに挿入する
// 定义一个有参数的ViewModel
class ParamsViewModel(
private val repository: Repository
) : ViewModel() {
fun test() {
repository.test()
}
}
class Repository() {
fun test() {
Log.d(TAG, "Repository test")
}
}
val viewModelModule = module {
single {
Repository() }
// 参数注解使用get()获取,无需手动传入
viewModel {
ParamsViewModel(get()) }
}
private val paramsViewModel: ParamsViewModel by viewModel()
paramsViewModel.test()
# log
Repository test
パラメータを持つものについてはViewModel
, Koin はこのパラメータをもう 1 ステップ注入することだけを要求し, 残りはパラメータを使用しない場合とほぼ同じです. オブジェクトを渡す必要があり, 次にこのオブジェクトを最初に に注入し, Koin にそれがシングルトン オブジェクトであることを伝え, それを直接渡すことができ (注入にも使用できます), そして注入時に Koin のメソッドParamViewModel
を通じてRepository
それmoudle
をsingle{}
取得factor{}
できViewModel
ますget()
。ここではKoinが非常に人気があり、面倒なパスを介して必要なパラメータを手動で作成する必要がないと思いますかViewModelProvider.Factory
。
さて、Koin の最初の記事はここまでです。その後、Koin のスコープ関連の知識を紹介します。
転載:https://blog.csdn.net/YoungOne2333/article/details/130843477