Um robuste Applikationen zu bauen ist es sinnvoll Control und Model von der View zu entkoppeln. Das ist bei Android Apps besonders wichtig, da die Views zur Laufzeit häufig ausgetauscht werden. Hat man weiter asynchrone Ereignisse im System (zum Beispiel Bluetooth oder GCM) muss man sich intensiv um um Synchronisation und Konsistenz Gedanken machen. Gängige Praxis ist, Control und Model in einen Android Service auszulagern. Der Service läuft permanent im Hintergrund und stellt so die Konsistenz des Models sicher. Die Kommunkation mit Android Bordmitteln kann dabei aber zu einer unüberschaubaren Anzahl von Intents, Handlern, AsyncTasks usw. führen. Ein Alternativie zur Android-Bordmitteln für die In-App-Kommunikation bietet ein Eventbus wie zum Beispiel: https://github.com/greenrobot/EventBus.
Item-Discovery-App
Als Prototyp wurde eine App erstellt, welche im Hintergrund Items generiert. Diese werden in einem Fragement dargestellt und können dort gelöscht werden. Den kompletten Code zu den Beispielen findet man hier.
Eventhandling
ItemDiscovery (Control)
ItemDiscovery erzeugt zufällige Items und stellt die Liste der Items nach jeder Änderung auf den Eventbus.
public void itemListChanged() { UpdatedListEvent e = new UpdatedListEvent(list); EventBus.getDefault().postSticky(e); }
ItemListFragment (View)
Während auf der View die Events im MainThread laufen…
public void onEventMainThread(final UpdatedListEvent e) { adapter.itemsUpdated(e.getItemList()); }
ItemListService (Model)
… werden auf dem Service sämtliche Events sequentiell im BackgroundThread ausgeführt. Damit entfallen unübersichtliche Handler, runOnUiThread oder Intents um den Service zu synrchronisieren.
public void onEventBackgroundThread(RemoveItemEvent e) { list.remove(0); itemListChanged(); }
Sticky
Ein nettes Feature ist, dass Events sticky gepostet werden können. Damit merkt sich der EventBus den letzten Event und stellt diesen bei der Registierung dem Konsument gleich zur Verfügung. Damit wird in unserem Fall wenn ItemListFragment startet automatisch onEventMainThread(final UpdatedListEvent e) aufgerufen ohne dass wir die Liste selbst anfragen müssen. Mehr zu den Sticky-Events hier.
Fazit
Wir haben mit dem Android EventBus eine saubere und elegante Trennung zwischen Model, Control und View sichergestellt. Der EventBus kommt ohne Annotationen aus und nutzt Reflection und Naming-Konventionen (onBackgroundThread). Wir haben mit dem EventBus gute Erfahrungen gesammelt und können den Einsatz vor allem in asynchronen und event-lastigen Apps empfehlen.
Pingback: Noser Blog Tackling the notorious IllegalStateException with the help of an Event Bus - Noser Blog