Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Injeção de Dependência

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Retrofit retrofit = new Retrofit.Builder()
 .baseUrl(baseUrl)
 .client(client)
 .callbackExecutor(mainThreadExecutor)
 .addCallAdapterFactory(callAdapterFactory)
 .addConverterFactory(converterFactory)
 .build();

Slide 5

Slide 5 text

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();

Slide 6

Slide 6 text

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();

Slide 7

Slide 7 text

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();

Slide 8

Slide 8 text

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();

Slide 9

Slide 9 text

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();

Slide 10

Slide 10 text

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();

Slide 11

Slide 11 text

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);

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Converter Factory Object Mapper BaseUrl OkHttp Retrofit API Service Cache Context

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

História

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

API

Slide 19

Slide 19 text

Voltando ao nosso exemplo…

Slide 20

Slide 20 text

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);

Slide 21

Slide 21 text

public class MainActivity extends Activity {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 }
 }


Slide 22

Slide 22 text

public class MainActivity extends Activity {
 ElifutService service;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 }
 }


Slide 23

Slide 23 text

public class MainActivity extends Activity {
 @Inject ElifutService service;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 }
 }


Slide 24

Slide 24 text

public class NetworkModule {
 
 }

Slide 25

Slide 25 text

@Module
 public class NetworkModule {
 
 }


Slide 26

Slide 26 text

@Module
 public class NetworkModule {
 Retrofit provideRetrofit() { 
 }
 }


Slide 27

Slide 27 text

@Module
 public class NetworkModule {
 @Provides Retrofit provideRetrofit() { 
 }
 }


Slide 28

Slide 28 text

@Module
 public class NetworkModule {
 @Provides Retrofit provideRetrofit() { return new Retrofit.Builder()
 .baseUrl(HttpUrl.parse("http://10.0.3.2:3000/"))
 .build();
 }
 }


Slide 29

Slide 29 text

@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);
 }
 }


Slide 30

Slide 30 text

public interface ElifutComponent { 
 }

Slide 31

Slide 31 text

@Component
 public interface ElifutComponent {
 
 }

Slide 32

Slide 32 text

@Component(modules = { NetworkModule.class })
 public interface ElifutComponent {
 
 }

Slide 33

Slide 33 text

@Component(modules = { NetworkModule.class })
 public interface ElifutComponent {
 ElifutService service();
 }

Slide 34

Slide 34 text

@Singleton
 @Component(modules = { NetworkModule.class })
 public interface ElifutComponent {
 ElifutService service();
 }


Slide 35

Slide 35 text

@Singleton
 @Component(modules = { NetworkModule.class })
 public interface ElifutComponent {
 ElifutService service();
 void inject(MainActivity mainActivity);
 }

Slide 36

Slide 36 text

@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();
 }
 }
 }

Slide 37

Slide 37 text

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);
 }
 }

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

Colocando tudo junto…

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

public class ElifutApplication extends Application {
 private ElifutComponent component;
 
 @Override public void onCreate() {
 super.onCreate();
 component = ElifutComponent.Initializer.init(this);
 }
 
 public ElifutComponent component() {
 return component;
 }
 }

Slide 42

Slide 42 text

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);
 }
 }

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

public class SampleClass {
 private final int anInteger;
 private final String aString;
 
 @Inject public SampleClass(int anInteger, String aString) {
 this.anInteger = anInteger;
 this.aString = aString;
 }
 }

Slide 46

Slide 46 text

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)

Slide 47

Slide 47 text

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);
 }
 }

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

Código gerado

Slide 50

Slide 50 text

@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);
 }


Slide 51

Slide 51 text

@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);
 }


Slide 52

Slide 52 text

@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);
 }
 }

Slide 53

Slide 53 text

@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);
 }
 }

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

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