Android
Pugnale 2
Ricerca…
Sintassi
- @Modulo
- @Component (dependencies = {OtherComponent.class}, modules = {ModuleA.class, ModuleB.class})
- DaggerMyComponent.create ()
- DaggerMyComponent.builder (). Mymodule (newMyModule ()). Create ()
Osservazioni
Non confondere con il pugnale di quadrato, il predecessore del pugnale 2.
Configurazione dei componenti per l'iniezione di applicazioni e attività
Un AppComponent
base che dipende da un singolo AppModule
per fornire oggetti singleton a livello di applicazione.
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(App app);
Context provideContext();
Gson provideGson();
}
Un modulo da utilizzare insieme a AppComponent
che fornirà i suoi oggetti singleton, ad esempio un'istanza di Gson
da riutilizzare nell'intera applicazione.
@Module
public class AppModule {
private final Application mApplication;
public AppModule(Application application) {
mApplication = application;
}
@Singleton
@Provides
Gson provideGson() {
return new Gson();
}
@Singleton
@Provides
Context provideContext() {
return mApplication;
}
}
Un'applicazione sottoclassata per l'impostazione di dagger e del componente singleton.
public class App extends Application {
@Inject
AppComponent mAppComponent;
@Override
public void onCreate() {
super.onCreate();
DaggerAppComponent.builder().appModule(new AppModule(this)).build().inject(this);
}
public AppComponent getAppComponent() {
return mAppComponent;
}
}
Ora un componente con ambito attività che dipende da AppComponent
per accedere agli oggetti Singleton.
@ActivityScope
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
E un ActivityModule
riutilizzabile che fornirà dipendenze di base, come un FragmentManager
@Module
public class ActivityModule {
private final AppCompatActivity mActivity;
public ActivityModule(AppCompatActivity activity) {
mActivity = activity;
}
@ActivityScope
public AppCompatActivity provideActivity() {
return mActivity;
}
@ActivityScope
public FragmentManager provideFragmentManager(AppCompatActivity activity) {
return activity.getSupportFragmentManager();
}
}
Mettendo tutto insieme siamo pronti e possiamo iniettare la nostra attività ed essere sicuri di usare lo stesso Gson
tutta l'app!
public class MainActivity extends AppCompatActivity {
@Inject
Gson mGson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.builder()
.appComponent(((App)getApplication()).getAppComponent())
.activityModule(new ActivityModule(this))
.build().inject(this);
}
}
Ambiti personalizzati
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {
}
Gli ambiti sono solo annotazioni e puoi crearne di tuoi laddove necessario.
Costruttore di iniezione
Le classi senza dipendenze possono essere facilmente create dal pugnale.
public class Engine {
@Inject // <-- Annotate your constructor.
public Engine() {
}
}
Questa classe può essere fornita da qualsiasi componente. Non ha dipendenze e non ha ambito . Non è necessario alcun altro codice.
Le dipendenze sono dichiarate come parametri nel costruttore. Dagger chiamerà il costruttore e fornirà le dipendenze, purché tali dipendenze possano essere fornite.
public class Car {
private Engine engine;
@Inject
public Car(Engine engine) {
this.engine = engine;
}
}
Questa classe può essere fornita da ogni componente se questo componente può anche fornire tutte le sue dipendenze - Engine
in questo caso. Poiché Engine
può anche essere iniettato dal costruttore, qualsiasi componente può fornire Car
.
È possibile utilizzare l'iniezione del costruttore ogni volta che tutte le dipendenze possono essere fornite dal componente. Un componente può fornire una dipendenza, se
- può crearlo usando l'iniezione del costruttore
- un modulo del componente può fornirlo
- può essere fornito dal componente principale (se è un
@Subcomponent
) - può usare un oggetto esposto da un componente da cui dipende (dipendenze dei componenti)
Utilizzo di @Subcomponent anziché di @Component (dependencies = {...})
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(App app);
Context provideContext();
Gson provideGson();
MainActivityComponent mainActivityComponent(ActivityModule activityModule);
}
@ActivityScope
@Subcomponent(modules = ActivityModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
public class MainActivity extends AppCompatActivity {
@Inject
Gson mGson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App)getApplication()).getAppComponent()
.mainActivityComponent(new ActivityModule(this)).inject(this);
}
}
Come aggiungere Dagger 2 in build.gradle
Dal rilascio di Gradle 2.2, l'uso del plugin per Android-apt non è più utilizzato. Deve essere usato il seguente metodo di impostazione di Dagger 2. Per la versione precedente di Gradle, utilizzare il metodo precedente mostrato di seguito.
Per Gradle> = 2.2
dependencies {
// apt command comes from the android-apt plugin
annotationProcessor 'com.google.dagger:dagger-compiler:2.8'
compile 'com.google.dagger:dagger:2.8'
provided 'javax.annotation:jsr250-api:1.0'
}
Per Gradle <2.2
Per utilizzare Dagger 2 è necessario aggiungere il plugin per android-apt
, aggiungere questo alla root build.gradle:
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
Quindi il build.gradle del modulo dell'applicazione dovrebbe contenere:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
…
}
final DAGGER_VERSION = '2.0.2'
dependencies {
…
compile "com.google.dagger:dagger:${DAGGER_VERSION}"
apt "com.google.dagger:dagger-compiler:${DAGGER_VERSION}"
}
Riferimento: https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2
Creazione di un componente da più moduli
Dagger 2 supporta la creazione di un componente da più moduli. Puoi creare il tuo componente in questo modo:
@Singleton
@Component(modules = {GeneralPurposeModule.class, SpecificModule.class})
public interface MyMultipleModuleComponent {
void inject(MyFragment myFragment);
void inject(MyService myService);
void inject(MyController myController);
void inject(MyActivity myActivity);
}
I due moduli di riferimento GeneralPurposeModule
e SpecificModule
possono quindi essere implementati come segue:
GeneralPurposeModule.java
@Module
public class GeneralPurposeModule {
@Provides
@Singleton
public Retrofit getRetrofit(PropertiesReader propertiesReader, RetrofitHeaderInterceptor headerInterceptor){
// Logic here...
return retrofit;
}
@Provides
@Singleton
public PropertiesReader getPropertiesReader(){
return new PropertiesReader();
}
@Provides
@Singleton
public RetrofitHeaderInterceptor getRetrofitHeaderInterceptor(){
return new RetrofitHeaderInterceptor();
}
}
SpecificModule.java
@Singleton
@Module
public class SpecificModule {
@Provides @Singleton
public RetrofitController getRetrofitController(Retrofit retrofit){
RetrofitController retrofitController = new RetrofitController();
retrofitController.setRetrofit(retrofit);
return retrofitController;
}
@Provides @Singleton
public MyService getMyService(RetrofitController retrofitController){
MyService myService = new MyService();
myService.setRetrofitController(retrofitController);
return myService;
}
}
Durante la fase di iniezione delle dipendenze, il componente prenderà gli oggetti da entrambi i moduli in base alle esigenze.
Questo approccio è molto utile in termini di modularità . Nell'esempio, esiste un modulo generico utilizzato per istanziare componenti come l'oggetto Retrofit
(utilizzato per gestire le comunicazioni di rete) e un PropertiesReader
(incaricato di gestire i file di configurazione). Esiste anche un modulo specifico che gestisce l'istanziazione di specifici controller e classi di servizio in relazione a quel componente specifico dell'applicazione.