Aufgaben-App Teil 3: Models und Manager

Aufgaben-App Teil 3: Models und Manager

Wir entwickeln gerade eine Aufgaben-App zum Erstellen einer Checkliste mit einzelnen Punkten, die sich abhaken lassen.

In diesem Video werden viele wichtige Grundlagen besprochen. Schau es dir ruhig mehrmals an, damit du alles verstehst. Auch dieser Artikel soll dir dabei helfen.

Models

Wir schreiben nicht unseren gesamten Code in das Hauptprogramm, sondern teilen ihn auf mehrere Klassen auf. Das erhöht die Übersichtlichkeit und Wiederverwendbarkeit. Es lässt uns unseren Code besser testen, erweitern und warten.

MVC-Muster

Als Konzept hierfür hat sich „MVC“ durchgesetzt. Das heißt man trennt Model, View und Controller voneinander, daher die drei Buchstaben M, V und C. View kennst du bereits, das sind unsere Elemente im Layout, die wir mit XML definieren. Controller kennst du eigentlich auch schon, das ist zum Beispiel unser Hauptprogramm, sprich die MainActivity.java. Nun wollen wir auch mit Models arbeiten, unserer dritten Komponente zu sauber getrenntem Code.

Was ist ein Model?

Ein Model bildet meist ein Element nach, das auch in der realen Welt existiert, also zum Beispiel ein Auto, eine Pizza, ein Schrank, eine Person, oder ähnliches. In unserer App haben wir beispielsweise eine Aufgabe, die so ein Model ist. Aufgaben gibt es auch in der realen Welt. Aufgaben haben Eigenschaften und man kann etwas mit ihnen machen. Man kann sie mit Adjektiven beschreiben, zum Beispiel „einfach“, „schwer“, „langwierig“. Man kann sie auch mit Verben nutzen, zum Beispiel „erstellen“, „erledigen“, „abhaken“, „delegieren“. All das sind Merkmale von Models.

Aufgaben-Model erstellen

Wir erstellen ein Model für unsere Aufgabe und nennen es wie im Englischen „Task“. Dazu erstellen wir eine neue Klasse in Android Studio.

Dieser Aufgabe geben wir alle Eigenschaften, die wir in unserer App benötigen. Zunächst reicht der Name der Aufgabe. Für jede Eigenschaft erstellen wir eine Methode zum Setzen der Eigenschaft und eine Methode zum Holen der Eigenschaft. Die erste nennt sich „Setter“, weil ein Wert gesetzt wird. Die zweite nennt sich „Getter“, weil ein Wert geholt wird. Das sieht dann so aus:

Manager

Es ist wie in der realen Welt. Ein Model kann gut aussehen, aber nicht alles machen, was nötig wäre, um in der realen Welt zu bestehen. Dazu braucht es einen Manager. Der Manager kümmert sich um das Model, manchmal auch um mehrere, und sagt ihr was zu tun ist.

Aufgaben-Manager erstellen

Wir brauchen einen Manager, der sich um die Aufgaben in unserer App kümmert. Wir nennen ihn einfach „TaskManager“. Dazu erstellen wir eine Klasse mit genau diesem Namen.

Der TaskManager kennt alle Tasks. Er verwaltet sozusagen eine Liste aller Aufgaben. Eine Liste können wir als Typ „ArrayList“ deklarieren. Dazu geben wir auch an, welche Art Models diese Liste enthält. In unserem Fall sind es Task-Models, also schreiben wir „ArrayList<Task>“.

Dann schreiben wir Methoden in unseren TaskManager zum Verwalten dieser Aufgabenliste. Man kann zum Beispiel Aufgaben hinzufügen und entfernen. Wir benötigen also eine Methode „addTask“ und eine „removeTask“. Die eine fügt der Aufgabenliste eine Aufgabe hinzu, die andere entfernt die Aufgabe, die ihr übergeben wird aus der Liste.

Zwei weitere Methoden werden später noch wichtig werden. Die eine soll die Aufgabenliste zurückgeben. Die andere soll einfach sagen, wieviele Aufgaben unsere Liste enthält. Zwar könnte jeder, der sich die Aufgabenliste vom TaskManager geben lässt, selbst durchzählen, wieviele Aufgaben sie enthält, wir wollen aber einen super freundlichen Manager entwickeln, der auch das Zählen für andere übernimmt. So etwas nennt man übrigens „Convenient Method“, also eine Methode, die nicht zwingend erforderlich ist, aber der Bequemlichkeit (convenience) dient.

Definition von Methoden

Bisher haben wir Methoden mit „protected“ geschrieben. „Protected“ gibt an, dass die Methoden nicht öffentlich ist. Sie kann nur aus der eigenen Klasse (und Klassen desselben Pakets) aufgerufen werden. Da der TaskManager aber Methoden für andere bereitstellt, die ihm Aufgaben geben können und Aufgaben wieder holen wollen, müssen einige seiner Methoden öffentlich sein. Daher schreiben wir „public“ statt „protected“.

Typ der Rückgabe

Neben public und protected müssen wir auch angeben, was eine Methode zurückgibt. Gibt sie gar nichts zurück schreiben wir „void“. Gibt sie einen Wert oder ein Objekt zurück, müssen wir den Typ angeben.

Schau dir die Methode „getTaskCount“ an. Hier zählen wir wieviele Aufgaben unsere Liste enthält und wollen die Anzahl zurückgeben. Die Anzahl ist eine natürliche ganze Zahl, also Typ „int“. Statt „void“ schreiben wir „int“.

Schau dir auch die Methode „getTaskList“ an. Hier wollen wir die gesamte Aufgabenliste zurückgeben. Die ist vom Typ „ArrayList“ und enthält Models vom Typ „Task“. Daher schreiben wir auch hier nicht „void“, sondern den konkreten Typ, also „ArrayList<Task>“.

Speichern und laden von Objekten

Wir wissen, dass wir einfache Daten mit Hilfe der SharedPreferences speichern und laden können. Das erkläre ich ausführlich im vierten Teil der Bumm-App Reihe. Schau dir das Video an, falls du das noch nicht getan hast. Klicke dazu hier.

Die SharedPreferences können aber keine komplexen Daten aufnehmen, also keine Models. Wir wollen aber die Liste unserer Aufgaben speichern, so dass sie auch erhalten bleiben, wenn man die App beendet und beispielsweise erst am nächsten Tag wieder öffnet. Da die Aufgabenliste aber Models enthält, nämlich Aufgaben (Tasks), können wir die SharedPreferences hierfür leider nicht verwenden. Wir brauchen eine Alternative.

Hawk

Der Android-Entwickler Orhan Obut hat Klassen geschrieben, die wir zum Speichern und laden von Models und Model-Listen verwenden können. Diese Klassen hat er zu einer so genannten Bibliothek zusammengefasst, also ein kleines Projekt, das andere Entwickler in ihrer App wieder nutzen können. Er nennt diese wiederverwendbare Bibliothek „Hawk“.

Um Hawk nutzen zu können, müssen wir in unserer Datei build.grade (Module: app) angeben, wo es zu finden ist. Wir fügen daher in den „dependencies“ diese Zeile hinzu.

implementation 'com.orhanobut:hawk:2.0.1'

Denk daran, anschließend in dem gelben Banner auf „Sync Now“ zu klicken, damit deine Änderungen übernommen werden. Android Studio wird dann die Hawk-Bibliothek herunterladen und wir können sie verwenden.

Wir fügen dem TaskManager zwei neue Methoden hinzu. Die eine soll unsere Aufgabenliste in Hawk speichern. Die andere soll unsere Aufgabenliste wieder aus Hawk laden. Das sieht dann so aus:

Diese beiden neuen Methoden müssen wir an den richtigen Stellen nutzen. Speichern wollen wir immer dann, wenn wir die Aufgabenliste ändern, also eine neue Aufgabe hinzufügen oder entfernen. Folglich müssen wir saveTaskList aufrufen in addTask und in removeTask.

Konstruktoren

Und wann laden wir die Aufgabenliste? Am besten ist es, die Liste zu laden, sobald der TaskManager genutzt wird, oder anders gesagt, sobald er „gebaut“ wird. Das gelingt mit dem so genannten Konstruktor. Der Konstruktor ist eine Methode, die immer dann automatisch aufgerufen wird, wenn die Klasse instanziiert wird, also immer dann, wenn im Code „new TaskManager“ steht.

So sieht der Konstruktor aus:

Hier gibt es eine Besonderheit. Wir müssen Hawk initialisieren. Das heißt wir rufen Hawk.init auf. Dazu muss der so genannte Context an Hawk übergeben werden. In unserem Fall ist die MainActivity unser Context. Daher erhält unser Konstruktor einen Parameter Context, der an Hawk weitergereicht wird. Danach laden wir die Aufgabenliste.

Manager im Hauptprogramm nutzen

Damit die Aufgaben gespeichert werden, die wir in unser Eingabefeld eintippen, müssen wir den TaskManager in unserem Hauptprogramm verwenden. Wir deklarieren ihn dazu oben in der MainActivity, dort wo auch die Views deklariert werden.

Dann instanziieren wir den TaskManager. Das machen wir am besten in der onCreate-Methode der MainActivity, also immer wenn das Hauptprogramm gestartet wird.

Nun passen wir die onSendButtonClick-Methode an. Die wird aufgerufen, wenn der Nutzer auf den Senden-Button klickt. Wir holen den Namen der Aufgabe aus dem Eingabefeld. Dann erstellen wir ein neues Task-Model, setzen den Namen, und übergeben das Model an den Manager, damit er es zu seiner Liste hinzufügen und speichern kann. Das sieht so aus:

Eingabefeld leeren

Nachdem der Nutzer auf den Senden-Button geklickt hat und die neue Aufgabe gespeichert wurde, sollten wir das Eingabefeld leer machen, damit der Nutzer direkt die nächste Aufgabe eintippen kann. Das geht so:

newTaskEditText.getText().clear();

Hervorragend! Das war’s für heute. Was fehlt noch? Richtig, wir müssen die Aufgabenliste noch in der App anzeigen und es ermöglichen, dass der Nutzer seine Aufgaben auch abhaken kann. Das machen wir beim nächsten Mal.

Quellcode herunterladen

Wenn du möchtest, kannst du dir den kompletten Quellcode der App herunterladen. Das kann dir helfen, falls du beim Nachbauen nicht weiterkommst. Klicke dazu hier.