Dagger 2 - Injeção de Dependência
-
Upload
edson-menegatti -
Category
Software
-
view
297 -
download
1
Transcript of Dagger 2 - Injeção de Dependência
Dagger 2INJEÇÃO DE DEPENDÊNCIA
Injecão de Dependência Dependência é qualquer objeto necessário
para o funcionamento de uma classe;
Desacoplamento entre classes de alto e baixo nível;
Inexistente, manual ou automática.
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; }}
Bibliotecas Guice
Dagger (v1)
Dagger 2
...
Funcionamento@Bind(R.id.home_iv) ImageView mImageView;
ButterKnife.bind(this, view);
view mImageView
findViewbyId
@Bind
mImageView = (ImageView)view.findViewbyId(R.id.home_iv);
Funcionamento
Component Object“findObjectOfTypeX”
@Inject
Module
Exemplo
Retrofit
bit.ly/di-android-meetup
Retrofit Servicepublic class GitHubApi {
public static final int CACHE_SIZE = 5 * 1024 * 1024;
public static <S> S createService(Class<S> 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<List<GitHubUser>> 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 + @Provides
Mecanismo para prover dependências
@Inject Mecanismo para requisitar dependências
@Component Ligação entre módulos e injeções
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<List<GitHubUser>> getUsers();
@GET("/users/{login}") @Headers("Authorization: token " + BuildConfig.GITHUB_TOKEN) Call<GitHubUser> getUser(@Path("login") String login);
@GET("/users") @Headers("Authorization: token " + BuildConfig.GITHUB_TOKEN) Call<List<GitHubUser>> 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);}
GitHubUserModel
Retrofit
OkHttpClient
Gson
NetworkModule#provideRetrofit
NetworkModule#provideHttpClient
NetworkModule#provideGson
GitHubService GitHubModule#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);}
Scopes Determinam a intenção de duração de ciclo de vida
de um component;
@Singleton é o único suportado out-of-the-box; Deve ser usado no nível de aplicação
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() {
activityScope1.append("123"); activityScope1.toString(); // output: "Activity123"
activityScope2.append("456"); activityScope2.toString(); // output: "Activity123456"
unscoped1.append("123"); unscoped1.toString(); // output: "Unscoped123"
unscoped2.append("456"); unscoped2.toString(); // output: "Unscoped456"
}}
Bonus Lazy; Inicialização de Map e Set; Producer assíncrono;
Conclusão Fácil acesso à variáveis compartilhadas;
Desacoplamento de dependências complexas;
Controle de ciclo de vida;
Performance.
Dúvidas?edson-menegatti-87898718
3dm1edson.menegatti.7
Referênciashttps://www.youtube.com/watch?v=oK_XtfXPkqwhttps://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2https://www.parleys.com/tutorial/5471cdd1e4b065ebcfa1d557/https://blog.gouline.net/2015/05/04/dagger-2-even-sharper-less-square/https://www.youtube.com/watch?v=SKFB8u0-VA0