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 full-size slide

  2. Injeção de Dependência

    View full-size 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 full-size slide

  4. Retrofit retrofit = new Retrofit.Builder()

    .baseUrl(baseUrl)

    .client(client)

    .callbackExecutor(mainThreadExecutor)

    .addCallAdapterFactory(callAdapterFactory)

    .addConverterFactory(converterFactory)

    .build();

    View full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  16. 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 full-size slide

  17. Voltando ao nosso exemplo…

    View full-size slide

  18. 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 full-size slide

  19. public class MainActivity extends Activity {


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

    }


    View full-size slide

  20. public class MainActivity extends Activity {

    ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

    }


    View full-size slide

  21. public class MainActivity extends Activity {

    @Inject ElifutService service;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

    }


    View full-size slide

  22. public class NetworkModule {


    }

    View full-size slide

  23. @Module

    public class NetworkModule {


    }


    View full-size slide

  24. @Module

    public class NetworkModule {

    Retrofit provideRetrofit() {

    }

    }


    View full-size slide

  25. @Module

    public class NetworkModule {

    @Provides
    Retrofit provideRetrofit() {

    }

    }


    View full-size slide

  26. @Module

    public class NetworkModule {

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

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

    .build();

    }

    }


    View full-size slide

  27. @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 full-size slide

  28. public interface ElifutComponent {

    }

    View full-size slide

  29. @Component

    public interface ElifutComponent {


    }

    View full-size slide

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

    public interface ElifutComponent {


    }

    View full-size slide

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

    public interface ElifutComponent {

    ElifutService service();

    }

    View full-size slide

  32. @Singleton

    @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {

    ElifutService service();

    }


    View full-size slide

  33. @Singleton

    @Component(modules = { NetworkModule.class })

    public interface ElifutComponent {

    ElifutService service();

    void inject(MainActivity mainActivity);

    }

    View full-size slide

  34. @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 full-size slide

  35. 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 full-size slide

  36. 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 full-size slide

  37. Colocando tudo junto…

    View full-size slide

  38. 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 full-size slide

  39. 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 full-size slide

  40. 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 full-size slide

  41. 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 full-size slide

  42. 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 full-size slide

  43. 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 full-size slide

  44. 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 full-size slide

  45. 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 full-size slide

  46. Código gerado

    View full-size slide

  47. @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 full-size slide

  48. @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 full-size slide

  49. @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 full-size slide

  50. @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 full-size slide

  51. 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 full-size slide