Android Architecture Components
An der diesjährigen Google IO wurden die Android Architecture Components vorgestellt.
Die Architecture Components sind ein Set von Libraries für den Lifecycle von UI Komponenten und Datenpersistenz. Die Komponenten helfen dabei eine robuste, testbare und wartbare App zu erstellen. Zudem soll weniger unnötiger Code geschrieben und Memory Leaks verhindert werden. Der Vorteil besteht darin, dass alles aus einer Hand kommt und nicht verschiedene Frameworks verwendet werden müssen. Gemäss Google ist dies erst der Anfang und weitere Architecture Components werden folgen.
Die Komponenten befinden sich erst im Entwicklungsstadium (Alpha-Status). Es könnte noch umfangreiche Änderungen geben bis es einen Stable-Release gibt.
Es handelt sich um die folgenden Komponenten:
- Lifecycle
- ViewModel
- Room
- LiveData

Empfohlene Architektur von Google (https://developer.android.com/topic/libraries/architecture/guide.html)
Ich habe ein kleines Adressbuch mit den Architecture Components erstellt. Zu finden ist es unter GitHub. Nachfolgend werden die Komponenten anhand des erstellten Adressbuchs genauer beschrieben.
Setup
Um die Architecture Components zu nutzen, muss das Google Maven Repository in build.gradle (Projekt-Level) hinzugefügt werden.
... allprojects { repositories { jcenter() maven { url "https://maven.google.com" } } } ...
Je nachdem welche Komponenten verwendet werden, müssen folgende Abhängigkeiten in build.gradle (Modul-Level) hinzugefügt werden.
Für Lifecycles, LiveData und ViewModel:
- compile “android.arch.lifecycle:runtime:1.0.0-alpha3”
- compile “android.arch.lifecycle:extensions:1.0.0-alpha3”
- annotationProcessor “android.arch.lifecycle:compiler:1.0.0-alpha3”
Für Room:
- compile “android.arch.persistence.room:runtime:1.0.0-alpha3”
- annotationProcessor “android.arch.persistence.room:compiler:1.0.0-alpha3”
Lifecycle
Mit den Lifecycle Komponenten lassen sich Klassen erstellen, die über den aktuellen Lifecycle von Actvities oder Fragments bescheid wissen und ihr Verhalten je nach Lifecycle-Status anpassen.
Nachfolgend sind zwei der Klassen aus dem Lifecycle Package genauer beschrieben.
LifecycleOwner
LifecycleOwner sind Objekte mit einem Lifecycle wie zum Beispiel Activities und Fragments.
Temporär gibt es die Klassen LifecycleActivity und LifecycleFragment, die von FragmentActivity beziehungsweise Fragment abgeleitet sind und das LifecycleOwner Interface implementieren. Diese werden verwendet um weitere Komponenten wie ViewModel und LiveData zu nutzen.
public class MainActivity extends LifecycleActivity { ... }
Hinweis: Da die Lifecycle Komponenten im Alpha-Status sind wird es noch nicht von Fragment und AppCompatActivity Klassen implementiert. Die Klassen LifecycleActivity und LifecycleFragment verschwinden im Stable-Release.
LifecycleObserver
LifecycleObserver beobachten LifecycleOwner und werden bei Lifecycle Änderungen informiert. LiveData, das weiter unten beschrieben wird, ist ein Beispiel für einen LifecycleObserver.
ViewModel
Das ViewModel enthält die UI-Logik und dient als Bindeglied zwischen View (Activities und Fragments) und Model. Der Name ViewModel kommt vom MVVM Pattern.
Der Vorteil am ViewModel ist, dass es nicht an den Lifecycle von Activities/Fragments gekoppelt ist. Das ViewModel verliert ihren Status nicht bei einer Bildschirmrotation oder anderen Konfigurationsänderungen.
Wenn eine Activity bei einer Bildschirmrotation erneut erstellt wird, bekommt sie die gleiche ViewModel Instanz die schon erstellt wurde. Die ViewModel Instanz wird erst beseitigt, wenn die Activity beendet (onDestroy()) wird.

Lifecycle von einem ViewModel (https://developer.android.com/topic/libraries/architecture/viewmodel.html)
Um eine Instanz von einem ViewModel zu bekommen, wird der ViewModelProvider verwendet:
AddressListViewModel viewModel = ViewModelProviders.of(this).get(AddressListViewModel.class);
Room
Room ist eine abstrakte SQLite Schicht und dient als ORM (Object-Relational Mapping) zwischen SQLite Tabellen und Java Objekten. Wenn man SQLite als Datenbank für Android nützt, ist Room sehr hilfreich.
Room besteht aus folgenden Hauptkomponenten:
- Entity
- DAO
- Database

Room Architektur Diagramm (https://developer.android.com/topic/libraries/architecture/room.html)
Nachfolgend sind die Komponenten von Room genauer beschrieben und wie ich sie genutzt habe:
Entity
Für jede Entity wird eine Datenbanktabelle erstellt. Mit der Annotation @Entity wird beschrieben, dass es sich um eine Room-Entität handelt. Der Primärschlüssel wird mit der Annotation @PrimaryKey gesetzt. Jedes Feld, das nicht die Annotation @Ignore hat, wird in der Datenbank persistiert.
@Entity(tableName = "address") public class AddressEntity { @PrimaryKey(autoGenerate = true) private int id; private String firstName; private String lastName; @Ignore private String fullName; }
DAO
DAO (Data Access Object) behandeln die Queries, die auf der Datenbank abgesetzt werden. Um das Interface zu nutzen wird die Annotation @Dao gesetzt. Beliebige SQL Queries werden mit der Annotation @Query geschrieben. Ein Nachteil ist, dass rohes SQL geschrieben werden muss. Jedoch werden die Queries zur Kompilierzeit überprüft. Ein nicht existierende Tabellenname wird zum Beispiel nicht akzeptiert. Insert, Update und Delete Operationen werden einfach mit den zugehörigen Annotationen ausgeführt.
Da es sich um ein Interface handelt, kann der Datenbankzugriff über DAO einfach für Tests gemockt werden.
@Dao public interface AddressDao { @Query("SELECT * FROM address") LiveData<List<AddressEntity>> loadAllAddresses(); @Query("select * from address where id = :addressId") LiveData<AddressEntity> loadAddress(int addressId); @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(AddressEntity address); @Update(onConflict = OnConflictStrategy.REPLACE) void update(AddressEntity address); @Delete void delete(AddressEntity address); }
Database
Um auf die Datenbank zuzugreifen, muss eine abstrakte Klasse erstellt werden, die von RoomDatabase abgeleitet ist. Bei der Liste entities in der Annotation @Database werden alle Datenbank-Entitäten aufgelistet.
@Database(entities = {AddressEntity.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract AddressDao addressDao(); }
Mit folgendem Code wird auf die erstellte Datenbank zugegriffen.
AppDatabase db = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) .build();
LiveData
LiveData ist ein Datenhalter der beobachtende Klassen bei Änderungen an den Daten informiert. LiveData ist ein LifecycleObserver. LiveData benachrichtigt die Klassen nur wenn sie in einem aktiven Lifecycle Status (STARTED oder RESUMED) sind.
In meiner Addressbuch App verwende ich LiveData kombiniert mit Room. Nachdem die Address-Daten aus der Datenbank geladen werden, wird das UI aktualisiert.
public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); viewModel = ViewModelProviders.of(this).get(AddressListViewModel.class); LiveData<List<AddressEntity>> addresses = viewModel.getAllAddresses(); addresses.observe(this, new Observer<List<AddressEntity>>() { @Override public void onChanged(@Nullable List<AddressEntity> addresses) { if (addresses != null) { addressListAdapter.addItems(addresses); } } }); }
Fazit
Das war nur ein kurzer Einblick in die Android Architecture Components. Weitere Informationen gibt es in der offiziellen Dokumentation.
Da es sehr wahrscheinlich noch umfangreiche Änderungen an den Komponenten geben wird und Klassen wieder verschwinden, würde ich sie noch nicht produktiv einsetzen. Es lohnt sich jedoch die Komponenten anzuschauen. Ich werde das Projekt Android Architecture Components weiter verfolgen und bin gespannt was noch kommt.
Der Source code der Adressbuch App ist zu finden unter GitHub.