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

Injeção de Dependência com Dagger

felipecsl
August 29, 2015

Injeção de Dependência com Dagger

Slides da minha apresentação de título "Deep-dive em Injeção de Dependência com Dagger" feita em 29/08/2015 na Android Dev Conference 2015.

felipecsl

August 29, 2015
Tweet

More Decks by felipecsl

Other Decks in Programming

Transcript

  1. Injeção de Dependência com
    Dagger
    iMasters Android Dev Conference 2015
    Felipe Lima
    @felipecsl

    View Slide

  2. Injeção de Dependência

    View Slide

  3. Injeção de Dependência
    É um Software Design Pattern
    Todo e qualquer sistema possui algum tipo de injeção de dependência
    Hollywood principle: "Don't call us, we'll call you”
    Frequentemente negligenciado

    View Slide

  4. Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(mainThreadExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  5. HttpUrl baseUrl = HttpUrl.parse("http://10.0.3.2:3000/");


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(mainThreadExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  6. HttpUrl baseUrl = HttpUrl.parse("http://10.0.3.2:3000/");

    OkHttpClient client = new OkHttpClient();


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(mainThreadExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  7. HttpUrl baseUrl = HttpUrl.parse(“http://10.0.3.2:3000/");
    OkHttpClient client = new OkHttpClient().setCache(cache);
    File cacheDir = new File(getCacheDir(), "okhttp");

    Cache cache = new Cache(cacheDir, 20L * 1024 * 1024);


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(mainThreadExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  8. HttpUrl baseUrl = HttpUrl.parse(“http://10.0.3.2:3000/");
    File cacheDir = new File(getCacheDir(), "okhttp");

    Cache cache = new Cache(cacheDir, 20L * 1024 * 1024);

    OkHttpClient client = new OkHttpClient().setCache(cache);

    ConcurrentUtil.MainThreadExecutor callbackExecutor =
    new ConcurrentUtil.MainThreadExecutor();


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(callbackExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  9. HttpUrl baseUrl = HttpUrl.parse(“http://10.0.3.2:3000/");
    File cacheDir = new File(getCacheDir(), "okhttp");
    Cache cache = new Cache(cacheDir, 20L * 1024 * 1024);

    OkHttpClient client = new OkHttpClient().setCache(cache);

    ConcurrentUtil.MainThreadExecutor callbackExecutor = 

    new ConcurrentUtil.MainThreadExecutor();

    RxJavaCallAdapterFactory callAdapterFactory =
    RxJavaCallAdapterFactory.create();


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(callbackExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  10. HttpUrl baseUrl = HttpUrl.parse("http://10.0.3.2:3000/");

    File cacheDir = new File(getCacheDir(), "okhttp");

    Cache cache = new Cache(cacheDir, 20L * 1024 * 1024);

    OkHttpClient client = new OkHttpClient().setCache(cache);

    ConcurrentUtil.MainThreadExecutor callbackExecutor =

    new ConcurrentUtil.MainThreadExecutor();

    RxJavaCallAdapterFactory callAdapterFactory =
    RxJavaCallAdapterFactory.create();

    ObjectMapper objectMapper = new ObjectMapper();

    Converter.Factory converterFactory =
    JacksonConverterFactory.create(objectMapper);


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(callbackExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View Slide

  11. HttpUrl baseUrl = HttpUrl.parse("http://10.0.3.2:3000/");

    File cacheDir = new File(getCacheDir(), "okhttp");

    Cache cache = new Cache(cacheDir, 20L * 1024 * 1024);

    OkHttpClient client = new OkHttpClient().setCache(cache);

    ConcurrentUtil.MainThreadExecutor callbackExecutor =

    new ConcurrentUtil.MainThreadExecutor();

    RxJavaCallAdapterFactory callAdapterFactory =
    RxJavaCallAdapterFactory.create();

    ObjectMapper objectMapper = new ObjectMapper();

    Converter.Factory converterFactory =
    JacksonConverterFactory.create(objectMapper);


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(callbackExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    ElifutService service = retrofit.create(ElifutService.class);

    View Slide

  12. Boilerplate
    ____________________________
    Não é bacana :(
    http://cdn.movieweb.com/img.news/NEnBKLdGEGLarq_1_1.jpg

    View Slide

  13. Converter
    Factory
    Object Mapper
    BaseUrl
    OkHttp Retrofit
    API Service
    Cache
    Context

    View Slide

  14. Não é este tipo de
    adaga…
    http://runescape.wikia.com/wiki/Steel_dagger

    View Slide

  15. Component E
    Component D
    Component C
    Component F Component B
    Component A
    Directed Acyclic Graph
    “DAG"-ger

    View Slide

  16. História

    View Slide

  17. Dagger 2
    Fork do Dagger 1 com foco
    em performance. Criado
    pelo Google.
    Spring
    Baseado em XML, validado
    em tempo de execução.
    Guice
    Baseado em Annotations e
    100% Java. Criado pelo
    Google.
    Dagger 1
    Evolução do Guice. Mais
    simples e focado em
    performance. Criado pela
    Square.
    História e Linha do Tempo
    200? 2006 2013 2014

    View Slide

  18. API

    View Slide

  19. Voltando ao nosso exemplo…

    View Slide

  20. HttpUrl baseUrl = HttpUrl.parse("http://10.0.3.2:3000/");

    File cacheDir = new File(getCacheDir(), "okhttp");

    Cache cache = new Cache(cacheDir, 20L * 1024 * 1024);

    OkHttpClient client = new OkHttpClient().setCache(cache);

    ConcurrentUtil.MainThreadExecutor callbackExecutor =

    new ConcurrentUtil.MainThreadExecutor();

    RxJavaCallAdapterFactory callAdapterFactory =
    RxJavaCallAdapterFactory.create();

    ObjectMapper objectMapper = new ObjectMapper();

    Converter.Factory converterFactory =
    JacksonConverterFactory.create(objectMapper);


    Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(callbackExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    ElifutService service = retrofit.create(ElifutService.class);

    View Slide

  21. public class MainActivity extends Activity {


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

    }


    View Slide

  22. public class MainActivity extends Activity {

    ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

    }


    View Slide

  23. public class MainActivity extends Activity {

    @Inject ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

    }


    View Slide

  24. public class NetworkModule {


    }

    View Slide

  25. @Module

    public class NetworkModule {


    }


    View Slide

  26. @Module

    public class NetworkModule {

    Retrofit provideRetrofit() {

    }

    }


    View Slide

  27. @Module

    public class NetworkModule {

    @Provides
    Retrofit provideRetrofit() {

    }

    }


    View Slide

  28. @Module

    public class NetworkModule {

    @Provides
    Retrofit provideRetrofit() {
    return new Retrofit.Builder()

    .baseUrl(HttpUrl.parse("http://10.0.3.2:3000/"))

    .build();

    }

    }


    View Slide

  29. @Module

    public class NetworkModule {

    @Provides
    Retrofit provideRetrofit() {
    return new Retrofit.Builder()

    .baseUrl(HttpUrl.parse("http://10.0.3.2:3000/"))

    .build();

    }

    @Provides
    ElifutService provideService(Retrofit retrofit) {

    return retrofit.create(ElifutService.class);

    }

    }


    View Slide

  30. public interface ElifutComponent {

    }

    View Slide

  31. @Component

    public interface ElifutComponent {


    }

    View Slide

  32. @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {


    }

    View Slide

  33. @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {

    ElifutService service();

    }

    View Slide

  34. @Singleton

    @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {

    ElifutService service();

    }


    View Slide

  35. @Singleton

    @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {

    ElifutService service();

    void inject(MainActivity mainActivity);

    }

    View Slide

  36. @Singleton

    @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {

    ElifutService service();

    void inject(MainActivity mainActivity);


    class Initializer {

    static ElifutComponent init() {

    return DaggerElifutComponent.builder()

    .networkModule(new NetworkModule())

    .build();

    }

    }

    }

    View Slide

  37. public class MainActivity extends Activity {

    @Inject ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    ElifutComponent.Initializer.init().inject(this);

    }

    }

    View Slide

  38. Recapitulando
    Agrupa dependências
    @Module
    Fornece dependências
    @Provides
    “Cola” entre módulos e
    injeções
    @Component
    Solicita dependências
    @Inject
    1 2 3 4

    View Slide

  39. Colocando tudo junto…

    View Slide

  40. View Slide

  41. public class ElifutApplication extends Application {

    private ElifutComponent component;


    @Override
    public void onCreate() {

    super.onCreate();

    component = ElifutComponent.Initializer.init(this);

    }


    public ElifutComponent component() {

    return component;

    }

    }

    View Slide

  42. public class MainActivity extends Activity {

    @Inject ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    ElifutApplication application = (ElifutApplication) getApplication();

    application.component().inject(this);

    }

    }

    View Slide

  43. Tipos de Injeção
    H T T P : // W W W . B O A S N O T I C I A S . P T / I M G / 1 3 2 3 8 6 6 8 9 4 C O L E S T R O L . J P G

    View Slide

  44. Via Construtor
    Mecanismo mais simples e intuitivo
    Anotação @Inject em um construtor da classe
    Cada argumento é uma dependência
    Dependências podem ser armazenadas em membros private e final
    Classe injetada fica implicitamente disponível para injeções subsequentes

    View Slide

  45. public class SampleClass {

    private final int anInteger;

    private final String aString;


    @Inject
    public SampleClass(int anInteger, String aString) {

    this.anInteger = anInteger;

    this.aString = aString;

    }

    }

    View Slide

  46. Via Membros da Classe
    Anotação @Inject em membros da classe
    Membros não podem ser privados ou final
    Injeção acontece depois de o objeto ter sido instanciado
    Método inject(this) deve ser chamado explicitamente para ocorrer a
    injeção
    Útil em casos onde não é possível injetar diretamente via construtor (ex.:
    Activity e Fragment)

    View Slide

  47. public class MainActivity extends Activity {

    @Inject ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    ElifutApplication application = (ElifutApplication) getApplication();

    application.component().inject(this);

    }

    }

    View Slide

  48. Via Método
    Anotação @Inject em métodos da classe
    Parâmetros do método são dependências
    É o caso de uso menos comum dos três

    View Slide

  49. Código gerado

    View Slide

  50. @Generated("dagger.internal.codegen.ComponentProcessor")

    public final class DaggerElifutComponent implements ElifutComponent {

    private Provider provideServiceProvider;

    private MembersInjector mainActivityMembersInjector;


    private DaggerElifutComponent(Builder builder) { 

    assert builder != null;

    initialize(builder);

    }


    private void initialize(final Builder builder) { 

    this.provideServiceProvider = ScopedProvider.create(
    NetworkModule_ProvideServiceFactory.create(
    builder.networkModule, provideRetrofitProvider));

    this.mainActivityMembersInjector =
    MainActivity_MembersInjector.create((MembersInjector)
    MembersInjectors.noOp(), provideServiceProvider);

    }


    @Override

    public void inject(MainActivity mainActivity) { 

    mainActivityMembersInjector.injectMembers(mainActivity);

    }


    View Slide

  51. @Generated("dagger.internal.codegen.ComponentProcessor")

    public final class DaggerElifutComponent implements ElifutComponent {

    private Provider provideServiceProvider;

    private MembersInjector mainActivityMembersInjector;


    private DaggerElifutComponent(Builder builder) { 

    assert builder != null;

    initialize(builder);

    }


    private void initialize(final Builder builder) { 

    this.provideServiceProvider = ScopedProvider.create(
    NetworkModule_ProvideServiceFactory.create(
    builder.networkModule, provideRetrofitProvider));

    this.mainActivityMembersInjector =
    MainActivity_MembersInjector.create((MembersInjector)
    MembersInjectors.noOp(), provideServiceProvider);

    }


    @Override

    public void inject(MainActivity mainActivity) { 

    mainActivityMembersInjector.injectMembers(mainActivity);

    }


    View Slide

  52. @Generated("dagger.internal.codegen.ComponentProcessor")

    public final class NetworkModule_ProvideServiceFactory implements
    Factory {

    private final NetworkModule module;

    private final Provider retrofitProvider;


    public NetworkModule_ProvideServiceFactory(NetworkModule module,
    Provider retrofitProvider) { 

    this.module = module;

    this.retrofitProvider = retrofitProvider;

    }


    @Override

    public ElifutService get() { 

    return module.provideService(retrofitProvider.get());

    }


    public static Factory create(NetworkModule module,
    Provider retrofitProvider) { 

    return new NetworkModule_ProvideServiceFactory(module,
    retrofitProvider);

    }

    }

    View Slide

  53. @Generated("dagger.internal.codegen.ComponentProcessor")

    public final class NetworkModule_ProvideServiceFactory implements
    Factory {

    private final NetworkModule module;

    private final Provider retrofitProvider;


    public NetworkModule_ProvideServiceFactory(NetworkModule module,
    Provider retrofitProvider) { 

    this.module = module;

    this.retrofitProvider = retrofitProvider;

    }


    @Override

    public ElifutService get() { 

    return module.provideService(retrofitProvider.get());

    }


    public static Factory create(NetworkModule module,
    Provider retrofitProvider) { 

    return new NetworkModule_ProvideServiceFactory(module,
    retrofitProvider);

    }

    }

    View Slide

  54. View Slide

  55. Obrigado!
    F E E D B A C K ? F E L I P E . L I M A @ G M A I L . C O M

    View Slide