2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
Koin MPP入門(全1記事)
リンクをコピー
記事をブックマーク
三好文二郎氏(以下、三好):「Koin MPP入門」ということで、お話ししようと思います。チームラボ株式会社の三好と申します。
簡単に自己紹介をします。Androidエンジニアになって3年ちょっと経ちました。主に「Spring」ですが、JVMのserver frameworkも触ります。SNSのアイコンは、シンバルだったりブロッコリー頭だったりするので、ぜひ探してみてください。よろしくお願いします。
まず簡単に「Koin」について紹介します。KoinはDSLで書ける軽量なDIコンテナライブラリです。今日は、すごく難しい使い方を紹介するのではなく、Multiplatformができるようになったので、簡単な使い方を紹介しようと思っています。
Koinは、Androidでよく使われるDIライブラリの「Dagger」とは違って、実行時に依存性のGraphの構築をします。内部では、instanceをhashMapで管理しています。
Android用の拡張、例えばViewModel、Service、WorkManager、Composeなどの対応が進んでいます。Serverでいえば、ケイター用のライブラリもあるのですが、今日はあまり触れません。3.0.0からMultiplatformに対応しました。
最初に基本的な使い方を紹介します。一番左の、sampleModuleという定数を宣言します。その中で、DSLで依存性を宣言していくのですが、singleで囲うとRepositoryのinstanceがsingletonで管理されます。
factoryで宣言すると、Factoryクラスのinstanceが毎回生成されます。あとでもう少し詳しく説明しますが、あるinstanceのlifecycleを、あるクラスのinstanceのlifecycleにひもづける時に、scopeで宣言します。
あるクラスにconstructor injectionをしたい場合ですが、引数は、get、もしくはpage injectionの対応をしています。また、あるクラスの中でフィールドとして使いたい時には、by injectのDelegateで、instanceを引っ張ってきます。
宣言を書いたら、startKoinという関数を呼び出して、先ほど定義したModuleをmodulesの中に書きます。こうすることで、instanceのhashMapで管理してくれるようになります。
次に、Type Bindingについて説明します。Koinは、KClassをよしなにStringのIDにして、それをkeyにしてhashMapで管理しています。
1つのmapに対して、複数のkeyを設定することもできます。一番上のコードでいえば、singel{ServiceImpl()}と宣言すると、ServiceImplクラスのinstanceを取ってくる時にしか引っ掛かりません。
2番目の、singleのジェネリクスのServiceインターフェイスにすると、ServiceインターフェイスでしかServiceImplクラスのinstanceが引っ張ってこられません。
single{ServiceImpl() as Service}というかたちで、型をダウンキャストしてしまうと、Serviceクラスでしか引っ張ってこられません。
single{ServiceImpl()} bind Service、インターフェイスというかたちに宣言すると、ServiceImplクラスとServiceインターフェイスの両方に引っ掛かって、instanceを取得できるようになります。
先ほどあとで少し説明しますと話した、Scopeですね。instanceのlifecycleを、あるクラスのinstanceのlifecycleにひもづけます。scopeのownerクラスに対しては、KoinScopeComponentというインターフェイスがあるので、それの実装が必要です。Moduleの宣言は、右に書いてあるかたちになります。
ScopeOwnerクラスを、コンストラクタで普通にinstanceを生成すると、今だとInstancePrinterというクラスのinstanceを生成して、先ほど作ったScopeOwnerクラスのinstanceを破棄します。
今だとすごくシンプルな書き方をしているので、ほぼ意味はないのですが、一緒にInstancePrinterをKoinのmapから削除できます。
次に、Qualifierです。先ほどKoinはKotlinクラスのmapで管理していると言ったのですが、それに余分な情報を追加してinstance管理させることができます。
付与できる情報は、StringとTypeとEnumの3種類です。namedという関数、もしくはqualifireのジェネリクスでクラスを指定。もしくは、Enumに対して、qualifireという拡張関数が定義されているので、それを使ってEnumを指定して、同一クラスを複数種類管理させることができます。
パッとコード見てもらうとわかると思うのですが、拡張関数とDelegateがすごくたっぷりあるので、特にKotlin側で簡単に使う分にはすごく便利です。
「Swift」からはすごく呼びづらいですね。Swiftから呼びづらいところですが、「Kotlin/Native」は、KotlinクラスからObjective-Cのクラスだったり、Objective-Cのプロトコルだったりします。
その際に変換が入っていて、単純なKotlinクラスではなくなってしまっているので、とても使いづらくなっています。
例えばですが、型でQualifireを作る時は引数がKClassになっています。DIコンテナからinstanceを取得する時には、KClassをkeyにしているので、KClassを指定してinstanceを引っ張ってきます。
Qualifireも同様に、KClassをQualifireに変換するというかたちなので、基本的にKClassが必要になってきます。
そのため、Objective-CのクラスやプロトコルをKotlinのクラスに変換できるkotlinx.cinterop関数が定義されています。getOriginalKotlinClassの引数は、ObjCClass、もしくはObjCProtocolの2種類です。
実際にどう使っていくのかですが、Multiplatform側に、今書いているような拡張関数を作成してみましょう。
ObjCClassを引数に受け取って、そこからKClassに変換して、Koinからinstanceを引っ張ってきて返す、もしくはプロトコルを受け取って、Kotlinクラスに変換して、Koinからinstanceを引っ張ってくるという拡張関数を定義します。
これはSwiftのコードですが、そうすることでKoinのinstanceからスッキリ呼び出せるようになりました。ただ、Force Castを毎回書かなければいけないというのは、少し冗長に感じます。
もう1個、Swift側で拡張関数を書きます。プロトコルの場合は上、クラスの場合は下ですね。簡単な拡張関数を作成すると、もっとスッキリ呼び出せるようになります。
コンテナから呼び出すほうはおしまいです。
Qualifireを作成するのも同様に、ObjCProtocol、もしくはObjCClassを引数にして、もとのKotlinクラスを変換して、それぞれTypeQualifireを作成する関数を書くと、スッキリ呼び出せるようになります。
メインのKoinの使い方の話はおしまいですが、よくある管理方法だと、Multiplatformのリポジトリが別管理になっていて、publishをしたけれど、DIの定義が間違っていてクラッシュすることがあります。それを直すためにもう1回直して、publishしてartifactを出さなきゃいけない、みたいなことがあると思うのですが、Koinは、Android側でModule定義のテストが書けます。
久保出さんの発表でもあったのですが、主要なモックのlibraryがKotlin/Nativeに対応していないので、JVMだけでテストできます。「koin-test-junit4」か「koin-test-jnit5」、「mockito」か「mockk」を組み合わせてテストを書けます。
テストは、KoinTestというインターフェイスがあるので、それを実装して、MockProviderRuleを当てはめる必要があります。
実際のテストですが、下のcheckModelesのDSLの中に、作成したModuleの定義を書いて、JUnitで実行させるだけです。
以上で発表はおしまいです。サンプルは「GitHub」のリポジトリに上げているので、ぜひ見てみてください。パッと動かせるようになっていると思うので、試してもらえればなと思います。
ご清聴ありがとうございました。
司会者:三好さんありがとうございます。1点、久保出さんから質問です。「Mobile.IOS、Mobile.ANDROIDは、KoinのAPIですか?」。これに関してはいかがでしょうか?
三好:いえ、単なるEnumの定義です。ちょっとわかりやすくなかったかもしれませんが、普通の単なるEnumです。
司会者:なるほど、ありがとうございます。
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略