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

Injecting Dependencies with Dagger 2

Injecting Dependencies with Dagger 2

Talk given at GDG DevFest Nord Italia 2016 in MIlan

Roberto Orgiu

November 12, 2016
Tweet

More Decks by Roberto Orgiu

Other Decks in Programming

Transcript

  1. INJECTING DEPENDENCIES WITH DAGGER 2 WHO’S SPEAKING? ▸ Android Developer

    @ Ennova, Italy ▸ Kotlin lover @ the same place @_tiwiz tiwiz
  2. Different kinds of Dependency Injection class Example { private ConstructorDependency

    cd; private MethodDependency md; Example(ConstructorDependency cd) { this.cd = cd; //Constructor Dependency Injection } public setMethodDependency(MethodDependency md) { this.md = md; //Method Dependency Injection } }
  3. THE ANDROID WAY SETTING UP THE ENVIRONMENT - 1 buildscript{

    ... dependencies{ ... classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’ } }
  4. THE ANDROID WAY SETTING UP THE ENVIRONMENT - 2 apply

    plugin: ‘com.neenbedankt.android-apt’
  5. THE ANDROID WAY SETTING UP THE ENVIRONMENT - 3 dependencies{

    ... compile ‘com.google.dagger:dagger:2.7’ apt ‘com.google.dagger:dagger-compiler:2.7’ provided ‘javax.annotation:jsr250-api:1.0’ }
  6. THE ANDROID WAY SETTING UP THE ENVIRONMENT - 3 dependencies{

    ... compile ‘com.google.dagger:dagger:2.7’ apt ‘com.google.dagger:dagger-compiler:2.7’ provided ‘javax.annotation:jsr250-api:1.0’ }
  7. THE ANDROID WAY SETTING UP THE ENVIRONMENT - 3 dependencies{

    ... compile ‘com.google.dagger:dagger:2.7’ apt ‘com.google.dagger:dagger-compiler:2.7’ provided ‘javax.annotation:jsr250-api:1.0’ } @Generated
  8. WHAT? MODULES @Module public class ApplicationModule { private final Context

    context; public ApplicationModule(Context context) { this.context = context; } @Provides @Singleton public Context providesContext() { return context; } @Provides @Singleton public ConnectivityManager providesConnectivityManager(Context context) { return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); } }
  9. WHAT? MODULES @Module public class ApplicationModule { private final Context

    context; public ApplicationModule(Context context) { this.context = context; } @Provides @Singleton public Context providesContext() { return context; } @Provides @Singleton public ConnectivityManager providesConnectivityManager(Context context) { return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); } }
  10. WIRING EVERYTHING UP! BUILDING IN THE APPLICATION public class App

    extends Application{ private ApplicationComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerApplicationComponent.builder() .applicationModule(new ApplicationModule(this)) .build(); } public ApplicationComponent getComponent() { return component; } }
  11. WIRING EVERYTHING UP! BUILDING IN THE APPLICATION public class App

    extends Application{ private ApplicationComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerApplicationComponent.builder() .applicationModule(new ApplicationModule(this)) .build(); } public ApplicationComponent getComponent() { return component; } }
  12. WIRING EVERYTHING UP! @INJECT ALL THE THINGS! public class MainActivity

    extends AppCompatActivity { @Inject ConnectivityManager manager; @Override protected void onCreate(Bundle savedInstanceState) { ... ((App) getApplication()).getComponent().inject(this); } }
  13. WIRING EVERYTHING UP! @INJECT ALL THE THINGS! public class MainActivity

    extends AppCompatActivity { @Inject ConnectivityManager manager; @Override protected void onCreate(Bundle savedInstanceState) { ... ((App) getApplication()).getComponent().inject(this); } } 1
  14. GETTING TO KNOW DAGGER 2 MOAR FEATUREZ! ▸ Multiple modules

    ▸ Scopes ▸ Subcomponents ▸ Testing
  15. MOAR FEATUREZ! MULTIPLE MODULES public class App extends Application{ private

    ApplicationComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerApplicationComponent.builder() .applicationModule(new ApplicationModule(this)) .secondModule(new SecondModule()) .build(); } public ApplicationComponent getComponent() { return component; } }
  16. DAGGER IS ABLE TO RETRIEVE DEPENDENCIES DECLARED IN OTHER MODULES

    OF THE SAME COMPONENT WITHOUT THE NEED OF DECLARE THEM EVERY TIME. MULTIPLE MODULES
  17. WHAT IF WE WANTED MORE AND DIFFERENT OBJECTS OF THE

    SAME TYPE? The curious Android Developer in the last line, on the left MULTIPLE MODULES
  18. MULTIPLE MODULES DIFFERENT OBJECT OF THE SAME TYPE @Provides @Named(IMAGE_URL)

    String provideImageUrl() { return ImageApiService.ENDPOINT; } @Provides @Named(URL) String provideBaseUrl() { return RestApiService.ENDPOINT; }
  19. MULTIPLE MODULES DIFFERENT OBJECT OF THE SAME TYPE @Provides @Named(IMAGE_URL)

    String provideImageUrl() { return ImageApiService.ENDPOINT; } @Provides @Named(URL) String provideBaseUrl() { return RestApiService.ENDPOINT; }
  20. MULTIPLE MODULES DIFFERENT OBJECT OF THE SAME TYPE @Provides @Named(IMAGE_URL)

    String provideImageUrl() { return ImageApiService.ENDPOINT; } @Provides @Named(URL) String provideBaseUrl() { return RestApiService.ENDPOINT; } @Provides @Singleton @Named(IMAGE_API_RETROFIT) Retrofit imageRetrofit(@Named(IMAGE_URL) String b, OkHttpClient client) { ... } @Provides @Singleton @Named(REST_API_RETROFIT) Retrofit retrofit(@Named(URL) String b, OkHttpClient client) { ... }
  21. MULTIPLE MODULES DIFFERENT OBJECT OF THE SAME TYPE @Provides @Named(IMAGE_URL)

    String provideImageUrl() { return ImageApiService.ENDPOINT; } @Provides @Named(URL) String provideBaseUrl() { return RestApiService.ENDPOINT; } @Provides @Singleton @Named(IMAGE_API_RETROFIT) Retrofit imageRetrofit(@Named(IMAGE_URL) String b, OkHttpClient client) { ... } @Provides @Singleton @Named(REST_API_RETROFIT) Retrofit retrofit(@Named(URL) String b, OkHttpClient client) { ... }
  22. GETTING TO KNOW DAGGER 2 MOAR FEATUREZ! ▸ Multiple modules

    ▸ Scopes ▸ Subcomponents ▸ Testing
  23. ALL THE ANNOTATIONS WORKS IN A WAY THAT THEY KEEP

    A SINGLE INSTANCE OF THE ANNOTATION ITSELF ALIVE AS LONG AS THE COMPONENT THEY ARE LINKED TO IS ALIVE SCOPES
  24. GETTING TO KNOW DAGGER 2 MOAR FEATUREZ! ▸ Multiple modules

    ▸ Scopes ▸ Subcomponents ▸ Testing
  25. GETTING TO KNOW DAGGER 2 MOAR FEATUREZ! ▸ Multiple modules

    ▸ Scopes ▸ Subcomponents ▸ Testing
  26. SUBCOMPONENTS WHAT ARE THEY? ▸ Components ▸ Need modules ▸

    Inherit from the parent ▸ Recently changed in Dagger 2.7
  27. SUBCOMPONENTS WHAT ARE THEY? ▸ Components ▸ Need modules ▸

    Inherit from the parent ▸ Recently changed in Dagger 2.7
  28. SUBCOMPONENTS BUILDING A SUBCOMPONENT public class App extends Application{ …

    private MyComponent myComponent; … public MyComponent createMyComponent() { return component.add(new MyModule()); } … }
  29. SUBCOMPONENTS BUILDING A SUBCOMPONENT public class App extends Application{ …

    private MyComponent myComponent; … public MyComponent createMyComponent() { return component.add(new MyModule()); } … }
  30. SUBCOMPONENTS INJECTING THE SUBCOMPONENT public class MyActivity extends AppCompatActivity {

    @Override protected void onCreate(Bundle savedInstanceState) { … ((App) getApplication()).createMyComponent().inject(this); … } }
  31. SUBCOMPONENTS INJECTING THE SUBCOMPONENT public class MyActivity extends AppCompatActivity {

    @Override protected void onCreate(Bundle savedInstanceState) { … ((App) getApplication()).createMyComponent().inject(this); … } }
  32. IF YOU RETAIN THE SUBCOMPONENT IN A FIELD, REMEMBER TO

    CLEAR IT WHEN YOU ARE DONE. SUBCOMPONENTS
  33. GETTING TO KNOW DAGGER 2 MOAR FEATUREZ! ▸ Multiple modules

    ▸ Scopes ▸ Subcomponents ▸ Testing
  34. TESTING WITH DAGGER 2 STEPS ▸ Extend component ▸ Create

    mock modules ▸ Extend application ▸ Extend test runner ▸ Profit
  35. TESTING WITH DAGGER 2 - STEPS EXTENDING THE COMPONENT ▸

    We need to do it so that we can pass in mock modules @Singleton @Component(modules = { TestAndroidModule.class, CommonModule.class }) public interface TestApplicationComponent extends ApplicationComponent { void inject(MainActivity mainActivity); }
  36. TESTING WITH DAGGER 2 - STEPS EXTENDING THE MODULES ▸

    So that we can pass in mocked objects @Module public class TestAndroidModule { @Provides @Singleton MockedStuff provideMockedStuff() { … } }
  37. TESTING WITH DAGGER 2 - STEPS EXTENDING THE APPLICATION ▸

    So that we can wire it all together public class MockApp extends MyApplication { private TestApplicationComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerTestApplicationComponent.builder() .testAndroidModule(new TestAndroidModule()) … .build(); } @Override public ApplicationComponent component() { return component; } }
  38. TESTING WITH DAGGER 2 - STEPS DO YOU RECALL THIS?

    android { defaultConfig { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } }
  39. TESTING WITH DAGGER 2 - STEPS LET’S EXTEND IT! public

    class MockTestRunner extends android.support.test.runner.AndroidJUnitRunner{ @Override public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return super.newApplication(cl, MockApp.class.getName(), context); } }