Upgrade to Pro — share decks privately, control downloads, hide ads and more …

안드로이드 DI 어떻게 하나요?

안드로이드 DI 어떻게 하나요?

2019년 12월 21일 GDG Android Dev Summit 2019 Extended 행사에서 발표한 자료입니다.
행사: https://festa.io/events/744
샘플코드: https://github.com/maryangmin/GDG-Dagger

Koin과 Dagger 중에 무엇이 좋나요? 그전에 DI를 왜 해야 하나요? 아니 DI는 뭔가요?
DI의 기본부터, 안드로이드에서 어떻게 적용하면 좋을지, Dagger2 중심으로 Android Dev Summit에서 나온 가이드를 소개합니다.

Seungmin 마량

December 21, 2019
Tweet

More Decks by Seungmin 마량

Other Decks in Programming

Transcript

  1. ߊ಴ ݾ಴ Koinҗ Dagger ઺ী ޖ঺੉ જաਃ? ৵ DIܳ ೧ঠ

    ೞաਃ? DIח ޥоਃ? DI੄ ӝࠄࠗఠ Androidীࢲ যڌѱ ੸ਊೞݶ જਸ૑, Android Dev Summitীࢲ աৡ о੉٘ܳ ࣗѐ೤פ׮.
  2. ݾର 1. DIח ޥоਃ? 2. DIో ޖ঺੉ જաਃ? 3. Dagger

    рױ ࢎਊߨ 4. Improving Dagger 5. Ѿۿ
  3. class Car( private val engine: Engine, private val battery: Battery,

    private val handle: Handle, private val padel: Padel, private val brake: Brake, private val radiator: Radiator ) { // Short Code } ए਍ ܻಖష݂
  4. class Car( private val engine: Engine, private val battery: Battery,

    private val handle: Handle, private val padel: Padel, private val brake: Brake, private val radiator: Radiator ) { // Short Code } ए਍ ܻಖష݂ Smaller-focused. ৉ೡਸ ա־঻׮. Loosed Coupling
  5. class CarTest { @Test fun carTest() { Car(FakeEngine()) } @Test

    fun carTest_fail() { Car(FakeFailEngine()) } } ए਍ పझ౟ ੄ઓࢿ Ү୓
  6. class CarTest { @Test fun carTest() { Car(FakeEngine()) } @Test

    fun carTest_fail() { Car(FakeFailEngine()) } } ए਍ పझ౟ ੄ઓࢿ Ү୓ Loosed Copuling
  7. AndroidInjector ੉ਊೞӝ @Component(modules = [ AndroidSupportInjectionModule::class, ActivityBindingModule::class ]) interface AppComponent

    : AndroidInjector<BaseApplication> { @Component.Builder interface Builder { fun build(): AppComponent } } AppComponent ࢶ঱
  8. AndroidInjector ੉ਊೞӝ @Component(modules = [ AndroidSupportInjectionModule::class, ActivityBindingModule::class ]) interface AppComponent

    : AndroidInjector<BaseApplication> { @Component.Builder interface Builder { fun build(): AppComponent } }
  9. AndroidInjector ੉ਊೞӝ @Module abstract class MainActivityModule { @Binds abstract fun

    mainView(activity: MainActivity): MainView } Module ࢶ঱ ੄ઓࢿ ࢤࢿ
  10. AndroidInjector ੉ਊೞӝ class BaseApplication : DaggerApplication() { fun applicationInjector(): AndroidInjector<out

    DaggerApplication> { return DaggerAppComponent.builder().application(this).build() } } class BaseActivity : DaggerActivity() class BaseFragment : DaggerFragment() Component ࢤࢿ DaggerApplication/Activity/Fragment ীࢲ Inject
  11. Google Guide ٮܰӝ @Component interface AppComponent { fun mainActivity(module: MainActivityModule):

    MainActivityComponent } @Subcomponent(modules = [MainActivityModule::class]) interface MainActivityComponent { fun inject(activity: MainActivity) } AppComponent / ActivitySubComponent ࢶ঱
  12. Google Guide ٮܰӝ @Module class MainActivityModule( private val activity: MainActivity

    ) { @Provides fun mainActivity(): MainActivity = activity @Provides fun mainView(activity: MainActivity): MainView = activity } Module ࢶ঱ ੄ઓࢿ ࢤࢿ
  13. Google Guide ٮܰӝ class MainActivity { @Inject lateinit var presenter:

    MainPresenter fun onCreate() { DaggerAppComponent.create() .mainActivity(MainActivityModule(this)) .inject(this) } } Component ࢤࢿ Module োѾ Inject
  14. @Module object DatabaseModule { @Provides @JvmStatic fun provideDB(context: Context): AppDatabase

    { // ... } } Dagger + Kotlin = ❤ @Module annotation support object class
  15. Dagger + Kotlin = ❤ @Module annotation support object class

    @Module object DatabaseModule { @Provides fun provideDB(context: Context): AppDatabase { // ... } } @JvmStatic ࢏ઁ
  16. Dagger + Kotlin = ❤ Support kotlin wildcards @Module class

    ConfigurationModule { @Provides fun provideConfigs(): List<@JvmSuppressWildcards String> { // ... } }
  17. Dagger + Kotlin = ❤ Support kotlin wildcards @Module class

    ConfigurationModule { @Provides fun provideConfigs(): List<String> { // ... } } @JvmSuppressWildcards ࢏ઁ
  18. Bind / Provide @Module abstract class MainActivityModule { @ActivityScope @Binds

    abstract fun mainView(activity: MainActivity): MainView }
  19. Bind / Provide @Module abstract class MainActivityModule { @ActivityScope @Binds

    abstract fun mainView(activity: MainActivity): MainView } Something Specific Cannot be Simple
  20. Module Discovery class MainActivity { @Inject lateinit var presenter: MainPresenter

    fun onCreate() { (applicationContext as BaseApplication).appComponent .mainActivity(MainActivityModule(this)) .inject(this) } } Module Discovery Inject
  21. Module Discovery @EntryPoint class MainActivity { @Inject lateinit var presenter:

    MainPresenter } Module Discovery ࢏ઁ ੗ز Inject
  22. Predefined Component @Module @InstallIn(ActivityComponent::class) class MainActivityModule( private val activity: MainActivity

    ) { @Provides fun mainActivity(): MainActivity = activity @Provides fun mainView(activity: MainActivity): MainView = activity } @InstallInਵ۽ Component োѾ
  23. Predefined Component @Module @InstallIn(AppComponent::class) class MainActivityModule( private val activity: MainActivity

    ) { @Provides fun mainActivity(): MainActivity = activity @Provides fun mainView(activity: MainActivity): MainView = activity }
  24. Predefined Component @Module @InstallIn(ServiceComponent::class) class MainActivityModule( private val activity: MainActivity

    ) { @Provides fun mainActivity(): MainActivity = activity @Provides fun mainView(activity: MainActivity): MainView = activity }
  25. Predefined Component @Module @InstallIn(SingletonComponent::class) class MainActivityModule( private val activity: MainActivity

    ) { @Provides fun mainActivity(): MainActivity = activity @Provides fun mainView(activity: MainActivity): MainView = activity } ޷ܻ ٜ݅য૓ Component ഝਊ Component ࢶ঱ ࢏ઁ
  26. @RunWith(AndroidJUnit4::class) class MainActivityTest { @Rule val testEntryPoint = TestEntryPointRule() @Inject

    lateinit var car: Car } InstrumentTest Module Discovery TestEntryPointRule ੗ز Inject
  27. @RunWith(AndroidJUnit4::class) class MainActivityTest { @Rule val testEntryPoint = TestEntryPointRule() @Inject

    lateinit var car: Car @TestModule object CarTestModule { @Provides fun provideFakeCar() = Car(FakeEngine()) } } Test only Module