Introduction à Dagger2 – Partie 2
Mise en place
Modules
Commençons par créer nos modules :
- GithubModule permettant de produire le GithubService et le Storage
- ContextModule permettant de fournir aux autre modules un Context
GithubModule.java
/** * Ce module permet de récupérer le GithubService et le Storage * Dagger2 va les crééer de façon unique (Singleton) et ils seront accessibles depuis le GithubComponent */ @Module public class GithubModule { /** * Retourne un Storage à Dagger2, construit avec le Context, injecté par Dagger2 * @param context Contexte de l'application, fournit par Dagger2 */ @Provides @Singleton public Storage provideStorage(Context context){ return new Storage(context); } /** * Créé le GithubService via Retrofit, qui réaliser les appels webservices, * en utilisant le StorageModule afin de gérer les clés * * @param storage le Storage injecté par Dagger2 via le StorageModule */ @Singleton @Provides public GithubService provideGithubService(final Storage storage) { return new RestAdapter.Builder() .setEndpoint(BuildConfig.URL_GITHUB) .setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { String key = storage.getApiKey(); if (key != null) { //ajoute aux header la ApiKey en clé bearer request.addHeader("bearer", key); } } }) .build() .create(GithubService.class); } }
La construction du GithubService prend en entrée un Storage, ce qui indique à Dagger que nous avons besoin d’une dépendance vers un objet Storage.
J’ai ajouté l’annotation @Singleton à mes méthodes, afin de ne créer qu’une seule instance de GithubService et de Storage. La construction du Storage nécessite un Context, qui sera fournir par ContextModule
ContextModule
/** * Ce module sert à fournir le contexte de l'application */ @Module public class ContextModule { private final Context context; /** * Nous ajoutons volontairement un constructeur qui prend un Context en entrée, * afin de lui fournir au runtime lors de la création de l'Application * @param context l'application créée */ public ContextModule(Context context) { this.context = context; } /** * Permet à Dagger2 de récupérer le context * @return le context de l'application */ @Provides Context provideContext() { return context; } }
Il faudra donc au moment de la création de l’application lui donner une référence vers le contexte courant, nous verrons plus tard comment le faire.
Components
Comme indiqué précédemment, les components sont les injecteurs, ils seront utilisés directement afin de récupérer les dépendances dans notre code (activités, fragments …).
Nous aurons ici un GithubComponent, permettant d’injecter nos dépendances dans nos différents contrôleurs.
GithubComponent.java
Composant principale de ce tutoriel, GithubComponent va utiliser Dagger2 afin de créer le GithubService et le Storage.
J’ai marqué ce composant est un singleton, c’est à dire qu’il n’existe qu’un fois lors de l’exécution de l’application.
modules = {ContextModule.class, StorageModule.class, RestModule.class} indique que ce Component utilisera les fonctions indiquées en @Provide de StorageModule, ContextModule et RestModule afin de générer les GithubService et Storage.
@Singleton @Component(modules = {ContextModule.class, StorageModule.class, RestModule.class}) public interface GithubComponent { GithubService githubService(); Storage storage(); //permet d'injecter une GithubService dans une instance de MainActivity void inject(MainActivity mainActivity); }
Dagger Component
Première étape, définir le Application.class de notre projet :
<application android:name=".Application" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
C’est dans cette classe que nous allons définir notre GithubComponent
Application est une classe assez spéciale sous Android, c’est la seule qui est vraiment « Singletonnée », nous utilisons ici cette spécificité pour stocker notre GithubComponent
public class Application extends android.app.Application { protected GithubComponent githubComponent; protected static Application application; @Override public void onCreate() { super.onCreate(); application = this; //je créé mon githubcompoent, et le stock dans mon application githubComponent = DaggerGithubComponent.builder() .contextModule(new ContextModule(getApplicationContext())) //on fournit le context .build(); } public static Application app() { return application; } //permet aux activités via .getApplication().appComponent() de récupérer le AppComponent public GithubComponent component() { return githubComponent; } }
L’accès à ce dernier se fera de la façon suivante
Application.app().component()
Voici comment va fonctionner Dagger2 dans notre exemple
public class MainActivity extends AppCompatActivity { @Inject GithubService githubService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //injecte le GithubService Application.app().component().inject(this); //on peux maintenant utiliser notre webservice REST via Retrofit this.githubService.listRepos("florent37", new Callback<List<Repo>>() { @Override public void success(List<Repo> repos, Response response) { Toast.makeText(MainActivity.this, repos.size() + " repos", Toast.LENGTH_LONG).show(); } @Override public void failure(RetrofitError error) { Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show(); } }); } }
Dagger est un outil très puissant, il est possible de faire bien plus que ce que je vous ai présenté lors de cette introduction.
Il est maintenant supporté par Google et rendu disponible sur Github, je vous invite donc à consulter la documentation officielle http://google.github.io/dagger/ afin d’apprendre à maitriser cet outil.
Les sources de ce tutoriel sont disponibles à l’adresse suivante : github