Accueil > Non classé > Android pour l’entreprise – 4 – Injection de dépendances

Android pour l’entreprise – 4 – Injection de dépendances

Cet article est la suite de Android pour l’entreprise – 3 – Déploiement hors market. Il appartient à la série Android pour l’entreprise, dont le fil conducteur est la réalisation d’une application Android d’annuaire d’entreprise : YMCA.Logo YMCA

Le thème du jour : Injection de dépendances au sein d’applications Android avec Google Guice. Le tout orchestré à l’aide du framework RoboGuice.

Injection de dépendances, mékeskidit ?

Comme je n’ai pas l’intention d’écrire un énième article tentant d’expliquer et de vulgariser l’injection de dépendances (et parce que je suis paresseux), je vous renvoie à deux ressources que je considère comme extrêmement instructives sur le sujet :

En deux mot :

  • l’injection de dépendance facilite les designs avec couplage faible, et nécessite des classes ayant une forte cohésion,
  • un composant comporte de manière générale des opérations, un état, des collaborateurs et des propriétés. Les propriétés sont de la configuration, les collaborateurs sont des outils dont se sert le composant. L’idée est de lui injecter ses collaborateurs et ses propriétés, pour que le composant puisse se concentrer sur l’essentiel.

javaPour résumer : l’injection de dépendances, c’est bon pour la maintenabilité et l’industrialisation d’applications, c’est bon pour la peau, et ça fait même le café.

La bonne nouvelle, c’est que l’injection de dépendances peut s’appliquer partout, et Android n’échappe pas à la règle.

Google Guice, prononcé “djouss”

Google Guice est un framework léger d’injection de dépendances pour les applications Java.

Mon but n’est pas de présenter en détail le fonctionnement de ce framework, je préfère vous laisser consulter directement le wiki officiel, qui est très complet.

Sachez simplement que :

  • les dépendances à injecter au sein d’un composant sont identifiées par l’annotation @Inject (sur les attributs ou sur le constructeur du composant) :

1
2
3
4
5
@Singleton
public class MyBean {
  @Inject
  private IMyService myService;
}
  • la configuration se fait à l’aide d’un DSL Java plutôt que via des fichiers de configuration. Cela permet notamment de bénéficier du typage fort. Par exemple, pour spécifier qu’une dépendance à un IMyService sera résolue avec l’implémentation MyServiceImpl, on écrit le code suivant :

1
bind(IMyService.class).to(MyServiceImpl.class);

Guice utilise en standard cglib pour permettre une réflection rapide et un support de l’AOP. Android ne supportant pas la génération dynamique de bytecode, une version spécifique de Guice a été créée : Guice 2.0 no AOP.

RoboGuice, prononcé “gloubiboulga” (oubliez, je taquine)

RoboGuice est un petit framework permettant d’adapter Google Guice au cycle de vie particulier des applications Android. De plus, il ajoute des fonctionnalités qui simplifient le développement Android.

Au chapitre des fonctionnalités spécifiques :

RoboGuice est actuellement disponible en 1.0-RC1 (et plus de 40 “fixed issues” depuis la 0.1).

Et RoboGuice infiltra YMCA

Et maintenant, place à la pratique ! La mise en place de RoboGuice est aisée, il suffit de suivre le guide (je vous passe les détails).

Injection du service de contacts

Pour obtenir le service de contacts, on utilisait jusqu’à présent une static factory, et le code suivant :


1
IContactListService contactListService = StaticContactListFactory.getRemoteFileService();

Désormais, on peut supprimer la static factory. On injecte le membre donné contactListService dans l’activité :


1
2
3
4
public class ContactListActivity extends GuiceActivity {
  @Inject
  private IContactListService    contactListService;
}

Et on réalise un binding au niveau du module de configuration :


1
bind(IContactListService.class).to(ContactListServiceRemoteFileImpl.class);

Injection de ressources

Dans Android, les ressources externalisées (String, Images, etc) sont identifiées par des int uniques, accessibles via la classe R. RoboGuice permet d’injecter directement ces ressources à partir de leur identifiant, c’est par exemple le cas dans ContactListServiceRemoteFileImpl :


1
2
@InjectResource(R.string.host)
private String  host;

Cette resource est définie dans le fichier res/values/config.xml :


1
<string name="host">http://10.0.2.2</string>

Injection de vues

De la même manière, il est possible d’injecter des vues (composants d’interface). Ainsi, le code suivant :


1
2
3
4
5
6
7
8
9
10
11
12
public class ContactListActivity extends Activity {

  private ListView                contactListView;

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.contact_list);

    contactListView = (ListView) findViewById(R.id.contact_list);
  }
}

Devient :


1
2
3
4
5
6
7
8
9
10
11
public class ContactListActivity extends GuiceActivity {

  @InjectView(R.id.contact_list)
  private ListView                        contactListView;

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.contact_list);
  }
}

Notez que l’injection des vues est réalisé lors de l’appel à setContentView().

Injection d’extra

Dernier point que je souhaite aborder, l’injection d’extra (des paramètres d’activité). Auparavant, il fallait vérifier que l’extra avait bien été transmis :


1
2
3
4
5
6
private Contact  contact;
[...]
contact = (Contact) getIntent().getSerializableExtra("contact_extra");
if (contact==null) {
  throw new NullPointerException("Should not be null, baaah");
}

Avec RoboGuice :


1
2
@InjectExtra("contact_extra")
private Contact  contact;

Dans tous les exemples précédents, vous pouvez utiliser ces annotations dans n’importe quel bean, et pas uniquement au sein des activités (pour les extra et les vues, il faut que les beans aient le scope @ContextScope ou default).

Pour plus d’exemples, vous pouvez consulter le code source de l’application exemple de RoboGuice, Astroboy.

Comme d’habitude :

Dans l’article suivant, nous aborderons la consommation de services REST JSON au sein d’une application Android.

Conclusion

Quel que soit le framework utilisé (et même sans framework), l’injection de dépendances est une bonne pratique. La combinaison Android + Guice via RoboGuice semble être une bonne option pour diminuer grandement la complexité du code, augmenter la maintenabilité, et se concentrer sur les aspects métier du code.

Il est probable que la mise en place de RoboGuice ait un léger impact au démarrage de l’application. A vous de placer le curseur entre optimisation à outrance et code maintenable, mais je pense que le jeu en vaut largement la chandelle. Et je profite de cette conclusion pour vous souhaiter à tous de joyeuses fêtes ;-) .

Share