infinite state machine

Dependecy Injection mit Roboguice

Introduction

user

Franziska Neumeister

Hat "Media Systems" studiert, entwickelt mobile Apps und will wissen, ob Androiden auch von elektrischen Schafen träumen


LATEST POSTS

Multithreading mit RxJava 18th April, 2016

Testbaren Code schreiben (Teil 1) 23rd April, 2015

Android

Dependecy Injection mit Roboguice

Posted on .

In der objektorientierten Programmierung sollte jede Klasse idealer Weise nur eine einzige Aufgabe erfüllen (Single Responsibility Prinzip). Manchmal spricht man auch davon, dass eine Klasse nur einen einzigen Grund für eine Änderung haben soll. Auf diese Weise entsteht ein modulares Netz an Objekten, die miteinander interagieren und die Abhängigkeiten der einzeln Klassen von einander werden minimal gehalten.

Warum Injection

Streng genommen ist auch das Erzeugen von Objekten eine eigenständige Aufgabe. Wenn ein Objekt seine Mitstreiter selber erzeugen muss, hat das gleich zwei Nachteile. Zum einen ist es fest an eine Implementierung dieser Objekte gebunden. Zum anderen muss es über Details bescheid wissen, wie andere Objekte konstruiert werden und schlimmsten falls auch wie ganze Objekt-Graphen erzeugt werden müssen.

Die Erzeugung von Objekten und die Geschäftslogik zu trennen reduziert also die Zahl an Abhängigkeiten einer Klasse und die Gründe ihre Implementierung anzupassen, wenn sich eine andere Klasse ändert.

Der häufigste Grund, die Instanzen auszutauschen, mit der ein Objekt kommuniziert, sind Unit-Tests, in denen echte Implementierungen durch Mock-Objekte ersetzt werden. So kann ein System in Isolation vom Rest seiner Umgebung getestet werden.

Eine einfache Möglichkeit die Herstellung von Objekten zu abstrahieren ist, sie in Fabrik-Objekte zu verlagern. Eine andere Lösung ist der Einsatz eines Dependency-Injection Frameworks, das den Aufbau von Objekt-Graphen übernimmt. In der  Java-Welt gibt es ein großes Angebot dieser Frameworks. Ein sehr verbreitetes für Android ist Roboguice. Es ist eine Portierung von Googles Guice-Frameworks für Android.

Es nutzt Annotationen, um Abhängigkeiten einer Klasse zu definieren und Reflexion, um zur Laufzeit die benötigten Kooperationspartner zur Verfügung zu stellen. Der Einsatz von Reflexionen führt zur einer Einbusse von Performance, erlaubt es aber auch dynamisch den Aufbau von Objekt-Graphen zu verändern. Eine Alternative, die auf Reflexion verzichtet, ist das Framework Dagger. Es legt bereits während des Build-Vorgangs den Aufbau der Objekt-Graphen fest.

Roboguice einrichten

Um Roboguice in einem Android Projekt zu benutzen muss es als erstes als Dependency in der build.gradle Datei des Moduls hinzugefügt werden

dependencies {
 compile 'org.roboguice:roboguice:3.+'
 provided 'org.roboguice:roboblender:3.+'
}

Als nächstes müssen alle Activities, Services und Fragments statt von den normalen Android Klassen von ihren Roboguice Versionen erben, z.B. RoboActivity, RoboIntentService, RoboDialogFragment u.s.w. Nur wenn an der Wurzel eines Objekt-Graphen eine Instanz steht, die von diesen Roboguice Klassen erbt, funktioniert die Dependency Injection.

public class CountersActivity extends RoboActionBarActivity {
}

Field Injection

Die einfachste Art, eine Abhängigkeit zu injizieren, ist einem Attribut einer Klasse die Annotation @Inject hinzuzufügen. 

public class ContactsActivity extends RoboActivity {
   @Inject
   LocationManager locationMng;

   @Override
   protected void onCreate(Bundle savedState) {
      super.onCreate(savedState);
      locationMng.getLastKnownLocation(null);
   }
}

Die Injektion passiert bei Activity- und Service-Klassen in der onCreate() Methode der Elternklasse. Die injizierten Objekte stehen also nachdem super.onCreate() aufgerufen wurde zur Verfügung. Bei Objekten, die über einen Konstruktor erzeugt werden, stehen die zu injizierenden Attribute erst nach Aufruf des Konstruktors zur Verfügung.

Constructor Injection

Die zweite Möglichkeit der Injektion ist die Abhängigkeiten als Argumente in der Konstruktor-Methode zu definieren und den Konstruktor mit der @Inject Annotation zu versehen.

class MusicFileHelper{
   AssetManager assets;

   @Inject
   public MusicFileHelper(AssetManager assets) {
      this.assets = assets;
   }
}

Java- und Android-Objekte injizieren

Roboguice kann alle Java-Objekte injizieren, die einen Default-Konstruktor haben und natürlich alle Objekte, deren Abhängigkeiten mit @Inject Annoatationen versehen sind.  Außerdem kann es viele Android-System-Objekte bereitstellen. Es gibt auch eine Lösung für Objekte, deren Erzeugung schwieriger ist, z.B. weil sie einen oder mehrere parametrisierte Konstruktoren haben oder mit einer statischen Fabrik erzeugt werden und auch nicht angepasst werden können, weil sie z.B. Teil einer externen Bibliothek sind. Dafür bietet Roboguice so genante Provider an, auf die in diesem Artikel aber nicht eingegangen wird.

profile

Franziska Neumeister

Hat "Media Systems" studiert, entwickelt mobile Apps und will wissen, ob Androiden auch von elektrischen Schafen träumen

Navigation