Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
How to use Dagger2 and Koin
Search
Hyeonji Jeong
April 05, 2019
Programming
2
1.1k
How to use Dagger2 and Koin
2019_정현지_droidknights
Dagger2 vs Koin 어떻게 쓰는 걸까요?
Hyeonji Jeong
April 05, 2019
Tweet
Share
More Decks by Hyeonji Jeong
See All by Hyeonji Jeong
2018 DevFest - Update to Oreo & Pie
hyunji92
0
120
droidknight_2018_nbt
hyunji92
0
59
devfest-AAC-2017-codelab
hyunji92
0
59
AAC-2017-soma
hyunji92
0
29
Other Decks in Programming
See All in Programming
Cline with Amazon Bedrockで爆速開発体験ハンズオン/ 株式会社ブリューアス登壇資料
mhan
0
110
カオスに立ち向かう小規模チームの装備の選択〜フルスタックTSという装備の強み _ 弱み〜/Choosing equipment for a small team facing chaos ~ Strengths and weaknesses of full-stack TS~
bitkey
1
130
プロフェッショナルとしての成長「問題の深掘り」が導く真のスキルアップ / issue-analysis-and-skill-up
minodriven
8
1.9k
七輪ライブラリー: Claude AI で作る Next.js アプリ
suneo3476
1
170
fieldalignmentから見るGoの構造体
kuro_kurorrr
0
130
ウォンテッドリーの「ココロオドル」モバイル開発 / Wantedly's "kokoro odoru" mobile development
kubode
1
260
Thank you <💅>, What's the Next?
ahoxa
1
590
Creating Awesome Change in SmartNews! En
martin_lover
0
110
サービスレベルを管理してアジャイルを加速しよう!! / slm-accelerate-agility
tomoyakitaura
1
200
ComposeでのPicture in Picture
takathemax
0
130
The New Developer Workflow: How AI Transforms Ideas into Code
danielsogl
0
100
音声プラットフォームのアーキテクチャ変遷から学ぶ、クラウドネイティブなバッチ処理 (20250422_CNDS2025_Batch_Architecture)
thousanda
0
380
Featured
See All Featured
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
137
33k
Done Done
chrislema
184
16k
Optimising Largest Contentful Paint
csswizardry
37
3.2k
Embracing the Ebb and Flow
colly
85
4.7k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.2k
Into the Great Unknown - MozCon
thekraken
38
1.7k
Product Roadmaps are Hard
iamctodd
PRO
53
11k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
YesSQL, Process and Tooling at Scale
rocio
172
14k
Unsuck your backbone
ammeep
671
57k
How STYLIGHT went responsive
nonsquared
100
5.5k
Transcript
%BHHFS WT ,PJO যڌѱॳחѦөਃ 4QFBLFS അ
ٜٜ۠࠙ਵदݶજणפ %BHHFS৬,PJOӝୡੋधҗद ਊߨਸঌҊरযೞחפযٜ࠙ਸਤೠ ߊܳೞ۰Ҋפ
য়טݾର ↟%*ۆޖੌө ↟%BHHFSۆޖੌө ↟,PJOۆޖੌө ↟%BHHFS৬,PJO җױޖੌө
↟ۧѱࢎਊ೧ࠁ ↟%BHHFS,PJOਊ೧ࠁӝ ↟ޖܻ۽ંী؊যܾө ↟%*ܳҕࠗೞҊۧѱਊೞݶܻоחѪޖੌө ↟݃ޖܻ
%*ۆޖੌө %FQFOEFODZ*OKFDUJPO
%*ۆޖੌө %FQFOEFODZ*OKFDUJPO
%*ۆޖੌө %FQFOEFODZ $MBTT$PGGFF GVONBLF-BUUF $MBTT.BUFSJBM GVONJML GVOFTQSFTTP
%*ۆޖੌө %FQFOEFODZ class Coffee { val material = Material() fun
makeLatte() { material.milk() material.espresso() } } class Material { fun milk() {} fun espresso() {} }
%*ۆޖੌө %FQFOEFODZ*OKFDUJPO
%*ۆޖੌө Ӓܿ߸҃ OFX.JML -BUUFё OFX&TQSFTTP Latte ё
উীࢲ ࢜۽ ёܳ ࢤࢿೞ ঋח!
%*ۆޖੌө فѐ࢚ݽٕաېझрѾبܳծ୶ӝਤ೧ ৻ࠗীࢲOFXёࢤࢿਸೞҊੑೞחѪ %* ઓࢿੑۆ
-BUUFё OFX4ZSVQ OFX.JML OFX&TQSFTTP
OFX*DF %*ۆޖੌө
-BUUFё OFX4ZSVQ OFX.JML OFX&TQSFTTP
OFX*DF %*ۆޖੌө "NFSJDBOPё OFX4ZSVQ OFX&TQSFTTP OFX*DF
%*ۆޖੌө OFX.JML -BUUFё OFX &TQSFTTP OFX4ZSVQ OFX*DF
%*ۆޖੌө OFX.JML -BUUFё OFX &TQSFTTP OFX4ZSVQ OFX*DF
"NFSJDBOPё
%*ۆޖੌө *0$ ৻ࠗ'SBNFXPSL OFX.JML OFX &TQSFTTP OFX4ZSVQ
OFX*DF -BUUFё
%BHHFSۆޖੌө
%BHHFSۆޖੌө উ٘۽٘ীࢲ ઓࢿੑਸҳഅೞӝਤ೧ ࢎਊೞחۄ࠳۞ܻ
ਫ਼Ӭ݅ঌҊֈযо %BHHFS %BHHFS
ਫ਼Ӭ݅ঌҊֈযо %BHHFS 4RVBSF %BHHFS (PPHMF
ਫ਼Ӭ݅ঌҊֈযо ਫ਼Ӭ݅ঌҊֈযо %BHHFS 3FGMFDUJPOוܻ ۠ఋ(SBQIҳࢿ
द
%BHHFSۆޖੌө
%BHHFSۆޖੌө ↟%FQFOEFODZJOKFDUJPOUPPM ↟BOOPUBUJPOQSPDFTTPSࢎਊ ↟OPSVOUJNFFSSPS ↟ࣽࣻ+BWB۽ܖয ↟OPSFGMFDUJPONPSFGBTU ↟੍ӝएHFOFSBUFEDPEF ↟QSPHVBSEࢸਃহ
%BHHFSۆޖੌө %BHHFSࣻѐ֛ *OKFDU $PNQPOFOU 4VCDPNQPOFOU .PEVMF 4DPQF 1SPWJEFT
%BHHFSۆޖੌө рױೞѱ !NPEVMF ҕә !$PNQPOFOU োѾ೧חઁҕ !*OKFDU ੑ߉חࣗ࠺
ಕۄڍٜܳ݅যࠅөਃ FTQSFTTP DPGGFF NJML -BUUFё
%FQFOEFODZ(SBQI " $ % #
ಕۄڍٜܳ݅যࠅөਃ FTQSFTTP DPGGFF NJML -BUUFё
%BHHFSۆޖੌө ઁ class Milk class Espresso class Coffee(var espresso: Espresso)
class Latte @Inject constructor( var coffee: Coffee, var milk: Milk) { fun makeLatteDrink() {} }
%BHHFSۆޖੌө ઁ @Module public class DrinkModule { @Provides Milk ProvideMilk(){
return Milk () } @Provides Espresso ProvideEspresso(){ return Espresso () } @Provides Coffee ProvideCoffee( var espresso: Espresso){ return Coffee (espresso) } }
%BHHFSۆޖੌө ઁ @Component(modules = {DrinkModule::class}) public interface DrinkComponent { fun
drink(): Latte fun inject(Activity: MainActivity) }
%BHHFSۆޖੌө ઁ class MainActivity : AppCompatActivity(){ override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) val latteComponent = DaggerDrinkComponent.builder() .drinkModule(DrinkModule()) .build() latteComponent.inject(this) latteComponent.drink() }
ಕۄڍٜܳ݅যࠅөਃ FTQSFTTP DPGGFF NJML -BUUFё
None
,PJOۆޖੌө ,PUMJOਸࢎਊೞחѐߊٜਸਤೠ पਊੋ"1*ઁҕਸೞח ҃ചػઓࢿੑۨਕ
,PJOۆޖੌө ↟4FSWJDF-PDBUPS1BUUFSOҳഅ ↟LPUMJO%4- بݫੋౠযࢎਊ ↟OPSFGMFDUJPO ↟QVSFLPUMJOਵ۽ܖযઉ
ਫ਼Ӭ 4FSWJDF-PDBUPS1BUUFSOਃj
,PJOۆޖੌө FTQSFTTP NJML NBUFSJBMT -PDBUPS 4FSWJDF-PDBUPS1BUUFSO ,PJOۆޖੌө
,PJOۆޖੌө ਫ਼Ӭ%4-ਃj
ಕۄڍٜܳ݅যࠅөਃ ,PJOۆޖੌө FTQSFTTP NJML NBUFSJBMT -PDBUPS
NPEVMF GBDUPSZ TJOHMF BMTPBMJBTFEBTCFBO CJOE
HFU TDPQF ,PJOࣻѐ֛ ,PJOۆޖੌө
,PJOۆޖੌө ઁ class Milk class Espresso class Coffee(var espresso: Espresso)
class Latte(var coffee: Coffee, var milk: Milk) { fun makeLatteDrink() {} }
,PJOۆޖੌө ઁ class MainApplication: Application() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) //start koin startKoin(this, listOf(myModules)) } } val myModules = module { single { Milk() } single { Espresso() } single { Coffee(get()) } single { Latte(get(), get())} }
,PJOۆޖੌө ઁ inline fun <reified T> get( qualifier: Qualifier? =
null, scope: Scope = this, noinline parameters: ParametersDefinition? = null ): T { return getKoin().get(T::class, qualifier, scope, parameters) ?: error("$this is not registered - Koin is null") }
,PJOۆޖੌө ઁ <reified T> SFJGJFEGVODUJPO
,PJOۆޖੌө ઁ inline fun <reified T> get( qualifier: Qualifier? =
null, scope: Scope = this, noinline parameters: ParametersDefinition? = null ): T { return getKoin().get(T::class, qualifier, scope, parameters) ?: error("$this is not registered - Koin is null") }
,PJOۆޖੌө ઁ class MainActivity : AppCompatActivity(){ val latte: Latte by
inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val latte: Latte = get() }
%BHHFS৬,PJO җױޖੌө
↟SFGMFDUJPOਸࢎਊೞঋ ↟য֢ప࣌ࢎਊਵ۽рױೠ٘ࢶ ↟ҕਬغחੋझఢझӔਸױࣽച ↟ࠂೠઓࢿएജ҃ࢸ ↟एਬాపझ %BHHFS
↟۞ழ࠳о֫ ↟৮߷ೠಌಖઁоহ ↟ઓҙ҅ীೠ٘ۨఊয۵ ↟য֢ప࣌ӝ߈ۄஹੌदрטযդ ஹੌয়ߡ٘ ↟݆ஹನք৬݆ੌਃ %BHHFSױ
↟য֢ప࣌җহযஹੌࡅܴ ↟णҗࢸऔ ↟,PUMJO%4-ࢎਊ ,PJO
↟۠ఋী۞оߊࢤ ↟࢜۽যܳߓਕঠೣ ↟ઁܳӝ൨ٞ ,PJOױ
Ӓېࢲ۽যڌѱࢎਊೞחѤؘਃ
ۧѱࢎਊ೧ࠁ ઁ(JUIVCਬѨ࢝ (JU)VC6TFS4FBSDI"1*ࢎਊ IUUQTEFWFMPQFSHJUIVCDPNWTFBSDI
ۧѱࢎਊ೧ࠁ%BHHFS @Singleton class GithubUserApiClient constructor( provideOkHttpClient: OkHttpClient) { var baseUrl
= "https://api.github.com" val userDataService: GithubUserApiService init { val retrofit = Retrofit.Builder() .baseUrl(baseUrl) .client(provideOkHttpClient) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build() userDataService = retrofit.create(GithubUserApiService::class.java) } }
ۧѱࢎਊ೧ࠁ%BHHFS @Module class ApiClientModule { @Provides fun provideOkHttpClient(): OkHttpClient {
val logging = HttpLoggingInterceptor() logging.level = HttpLoggingInterceptor.Level.BASIC return OkHttpClient.Builder() .addInterceptor(logging) .build() } @Provides fun provideGithubUserApiClient(): GithubUserApiClient { return GithubUserApiClient(provideOkHttpClient()) } }
ۧѱࢎਊ೧ࠁ%BHHFS @Module(includes = [ApiClientModule::class]) class GithubUserListModule(val view: MainPresenter.View) { @Provides
fun provideMainPresenter( presenter: MainPresenterImpl) : MainPresenter { return presenter } @Provides fun provideMainView(): MainPresenter.View { return view } }
ۧѱࢎਊ೧ࠁ%BHHFS @Component(modules = [GithubUserListModule::class]) interface GithubUserListComponent { fun inject(Activity: MainActivity)
}
ۧѱࢎਊ೧ࠁ%BHHFS class MainPresenterImpl @Inject constructor( val view: MainPresenter.View, val client:
GithubUserApiClient) : MainPresenter { @SuppressLint("CheckResult") override fun getGithubUserList(q: String) { client.userDataService.getUserData(q, "repositories", "desc") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({view.onDataLoaded(it)},{view.onDataFailed()},{}) } }
ۧѱࢎਊ೧ࠁ%BHHFS class MainActivity : AppCompatActivity(), MainPresenter.View { @Inject lateinit var
presenter: MainPresenter override fun searchGithubUser(searchWord: String) { if (searchWord.isNullOrBlank()) { toast("Ѩ࢝ػ о হणפ") userFragment.userAdapter.apply { items.clear() notifyDataSetChanged() } } else { presenter.getGithubUserList(searchWord) } } ... }
ۧѱࢎਊ೧ࠁ%BHHFS override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) //initialize
AppComponent var component = DaggerGithubUserListComponent.builder() .githubUserListModule(GithubUserListModule(this)) .build() component.inject(this) .. }
ۧѱࢎਊ೧ࠁ%BHHFS @Module(includes = [ApiClientModule::class]) class GithubUserListModule(val view: MainPresenter.View) { @Provides
fun provideMainPresenter( presenter: MainPresenterImpl) : MainPresenter { return presenter } @Provides fun provideMainView(): MainPresenter.View { return view } }
ۧѱࢎਊ೧ࠁزੌೠӝמઁ ઁ(JUIVCਬѨ࢝ (JU)VC6TFS4FBSDI"1*ࢎਊ IUUQTEFWFMPQFSHJUIVCDPNWTFBSDI
ۧѱࢎਊ೧ࠁ,PJO val userlistModule: Module = module { factory { MainPresenterImpl(get())
as MainPresenter<*> } }
ۧѱࢎਊ೧ࠁ,PJO val apiModule: Module = module { single { val
loggingInterceptor = HttpLoggingInterceptor() if (BuildConfig.DEBUG) { loggingInterceptor.level = HttpLoggingInterceptor.Level.BASIC } else { loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE } Retrofit.Builder() .baseUrl("https://api.github.com") .client(OkHttpClient.Builder().addInterceptor(loggingInterceptor).build()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build() .create(GithubUserApiService::class.java) } } val appModules = listOf(apiModule, userlistModule)
ۧѱࢎਊ೧ࠁ,PJO class MainApplication :Application() { override fun onCreate() { super.onCreate()
startKoin { // Android context androidContext(this@MainApplication) // modules modules(appModules) } } }
ۧѱࢎਊ೧ࠁ,PJO lass MainActivity : AppCompatActivity(), UserDataList { private val presenter:
MainPresenter<UserData> by inject() override fun searchGithubUser(searchWord: String) { if (searchWord.isNullOrBlank()) { presenter.getGithubUserList("a") userFragment.userAdapter.apply { items.clear() notifyDataSetChanged() } } else { presenter.getGithubUserList(searchWord) } } ... }
ۧѱࢎਊ೧ࠁ,PJO override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) presenter.userData
= this ... }
ࣁೠ٘ח(JUIVCীj IUUQTHJUIVCDPNIZVOKJ 'JOE/FX6TFST
ޖܻ۽ંী؊যܾө
%*ܳ൨ٜѱҕࠗ೧ࢲਊ೧оҊ ܻ۽ંӒܻҊܻਗٜ חҗোޖੋо
ઓࢿࢎਊਵ۽ח
↟୶࢚ചܳా೧ػёٜ࢚ഐਊী೧زੋܴоמ ↟۠ఋী߄ੋ٬غযઓࢿ৻ࠗীࢲੑغযઓبܳծ୶Ҋࢎਊоמ ↟ੑػ٘ӝמਸ߄ԲҊरਸٸ ݆٘ܳ߄Եਃоহ ↟ࢤࢿػੋझఢझझ ੋझఢࢤࢿҗࢤݺӝܳ %*ۨਕীࢲঌইࢲ೧ળ ઓࢿࢎਊਵ۽ח
݃ޖܻ Ӓېࢲަॳݶજױ݈ջ
݃ޖܻ ࢎप
݃ޖܻ ࢶఖীח଼ٮܲj
য়ےदрٜয࣊ࢲ хࢎפ