Dagger 2 - Inje§£o de Dependncia

  • View
    293

  • Download
    1

Embed Size (px)

Text of Dagger 2 - Inje§£o de Dependncia

PowerPoint Presentation

Dagger 2INJEO DE DEPENDNCIA

Injeco de DependnciaDependncia qualquer objeto necessrio para o funcionamento de uma classe;

Desacoplamento entre classes de alto e baixo nvel;

Inexistente, manual ou automtica.

public class ClassA {

private ClassB mClassB; public ClassA() { mClassB = new ClassB(); }}

public class ClassA {

private ClassB mClassB; public ClassA() { mClassB = new ClassB(new ClassC()); }}

public class ClassA {

private ClassB mClassB; public ClassA(ClassB classB) { mClassB = classB; }}

BibliotecasGuice

Dagger (v1)

Dagger 2

...

GuiceReflexo;

Deteco de erros apenas em runtime;

Inicializao e injeo lentas.

Dagger (v1)Dificuldade em obfuscar cdigo ou verificar cdigo fonte (map-like structure);

Reflexo para carregar classes geradas;

Erros ainda podem acontecer em runtime.

Dagger 2Erros de configurao em tempo de cdigo;

Facilidade de debug;

Sem reflexo (#perfmatters);

Menos flexvel classes fortemente tipadas.

9

Funcionamento@Bind(R.id.home_iv) ImageView mImageView;ButterKnife.bind(this, view);

viewmImageViewfindViewbyId@BindmImageView = (ImageView)view.findViewbyId(R.id.home_iv);

Funcionamento

ComponentObjectfindObjectOfTypeX@InjectModule

Exemplo

Retrofit

bit.ly/di-android-meetup

Retrofit Servicepublic class GitHubApi { public static final int CACHE_SIZE = 5 * 1024 * 1024;

public static S createService(Class serviceClass, Context context) { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); final Gson gson = gsonBuilder.create(); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(interceptor) .cache(new Cache(context.getCacheDir(), CACHE_SIZE)) .readTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS) .build(); Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(BuildConfig.API_URL).client(client).build(); return retrofit.create(serviceClass); }}

UserModelpublic class GitHubUserModel {

private final GitHubService mService;

public GitHubUserModel(Context context) { mService = GitHubApi.createService(GitHubService.class, context); } public Call fetchUsers(int page) { return mService.getUsers(page); } ... }GitHubUserModel userModel = new GitHubUserModel(getActivity().getApplicationContext());mActionInteractor = new UsersListPresenter(this, userModel);mActionInteractor.loadUsersList(false);

Introduzindo Dagger

Dagger API@Module + @ProvidesMecanismo para prover dependncias

@InjectMecanismo para requisitar dependncias

@ComponentLigao entre mdulos e injees

DaggerProject/build.gradle

buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8 }}

App/build.gradle

apply plugin: 'com.neenbedankt.android-apt'

compile 'com.google.dagger:dagger:2.0.2'apt 'com.google.dagger:dagger-compiler:2.0.2'provided 'org.glassfish:javax.annotation:10.0-b28'

@Modulepublic class NetworkModule {

public static final int CACHE_SIZE = 5 * 1024 * 1024;

@Provides public Retrofit provideRetrofit(Gson gson, OkHttpClient client) { return new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .baseUrl(BuildConfig.API_URL) .client(client) .build(); } @Provides public OkHttpClient provideHttpClient(HttpLoggingInterceptor interceptor, Cache cache) { return new OkHttpClient.Builder() .addInterceptor(interceptor) .cache(cache) .connectTimeout(60, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); }

@Provides public Cache provideCache(Application application) { return new Cache(application.getCacheDir(), CACHE_SIZE); }

@Provides public HttpLoggingInterceptor provideHttpInterceptor() { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); return interceptor; }

@Provides public Gson provideHttpGson() { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); return gsonBuilder.create(); }}

@Modulepublic class GitHubModule {

public interface GitHubService {

@GET("/users") @Headers("Authorization: token " + BuildConfig.GITHUB_TOKEN) Call getUsers();

@GET("/users/{login}") @Headers("Authorization: token " + BuildConfig.GITHUB_TOKEN) Call getUser(@Path("login") String login);

@GET("/users") @Headers("Authorization: token " + BuildConfig.GITHUB_TOKEN) Call getUsers(@Query("since") int page); }

@Provides public GitHubService provideGitHubService(Retrofit retrofit) { return retrofit.create(GitHubService.class); }}

@Modulepublic class AppModule {

private final Context mApplicationContext;

public AppModule(Context applicationContext) { mApplicationContext = applicationContext; }

@Provides @PerApp public Context provideApplicationContext() { return mApplicationContext; }}

@Component(modules = {AppModule.class, GitHubModule.class, NetworkModule.class})public interface AppComponent {

void inject(UsersListFragment fragment);}

DepencyInjectionApplication.java

@NonNullprotected DaggerAppComponent.Builder prepareAppComponent() { return DaggerAppComponent.builder() .networkModule(new NetworkModule()) .gitHubModule(new GitHubModule()) .appModule(new AppModule(this));}

GitHubUserModel.java

public class GitHubUserModel {

private final GitHubModule.GitHubService mService;

@Inject public GitHubUserModel(GitHubModule.GitHubService service) { mService = service; } ...}

UsersListFragment.java

@Inject public GitHubUserModel mUserModel;

@Overrideprotected void onCreate() { DepencyInjectionApplication.getAppComponent(getActivity()).inject(this);}

@Overrideprotected void onResume() { mActionInteractor = new UsersListPresenter(this, mUserModel); mActionInteractor.loadUsersList(false);}

GitHubUserModelRetrofitOkHttpClientGsonNetworkModule#provideRetrofitNetworkModule#provideHttpClientNetworkModule#provideGsonGitHubServiceGitHubModule#provideGitHubService

Component Dependency

@Component(modules={AppModule.class, NetworkModule.class})public interface NetComponent {

Retrofit retrofit();}

@Component(dependencies = NetComponent.class, modules = GitHubModule.class)public interface AppComponent {

void inject(UsersListFragment fragment);}public class DepencyInjectionApplication extends Application {private AppComponent mAppComponent;private NetComponent mNetComponent;

private void setupDaggerAppComponent() { mNetComponent = DaggerNetComponent.builder() .appModule(new AppModule(this)) // .networkModule(new NetworkModule()) is free .build();

mAppComponent = DaggerAppComponent.builder() // .gitHubModule(new GitHubModule()) is free .netComponent(mNetComponent) .build();}}

Subcomponent

@Subcomponent(modules = GitHubModule.class)public interface GitHubComponent {

void inject(UsersListFragment fragment);}

@Component(modules = {NetworkModule.class, AppModule.class})public interface AppComponent {

Application getApplication();

GitHubComponent plus(GitHubModule gitHubModule);}

DepencyInjectionApplication.javaprivate void setupDaggerAppComponent() { mAppComponent = DaggerAppComponent.builder() .appModule(new AppModule(this)) .build();}

UsersListFragment.java@Overrideprotected void onCreate() { DepencyInjectionApplication.getAppComponent(getActivity()) .plus(new GitHubModule()) .inject(this);}

@Overrideprotected void onResume() { mActionInteractor = new UsersListPresenter(this, mUserModel); mActionInteractor.loadUsersList(false);}

ScopesDeterminam a inteno de durao de ciclo de vida de um component;

@Singleton o nico suportado out-of-the-box;Deve ser usado no nvel de aplicao

Custom scopes permitem maior flexibilidade, mas cabe ao programador respeitar o ciclo de vida.

@Scope@Retention(RetentionPolicy.RUNTIME)public @interface PerActivity {}

@Modulepublic class MyActivityModule {

@PerActivity @Named("ActivityScope") @Provides StringBuilder provideStringBuilderActivityScope() { return new StringBuilder("Activity"); }

@Named("Unscoped") @Provides StringBuilder provideStringBuilderUnscoped() { return new StringBuilder("Unscoped"); }}

public class MyActivity {

@Inject @Named("ActivityScope") StringBuilder activityScope1;

@Inject @Named("ActivityScope") StringBuilder activityScope2;

@Inject @Named("Unscoped") StringBuilder unscoped1;

@Inject @Named("Unscoped") StringBuilder unscoped2;

public void onCreate() {

activitySc