android sqlite_wowomnom_Fotolia_85154667

Android SQLite Datenbank Tutorial – Teil 5: Mit der SQLite App auf Benutzereingaben reagieren


Im dritten Abschnitt werden wir dann das Gelernte in unserer SQLite App anwenden und die MainActivity-Klasse umstrukturieren und erweitern. Wir werden die Life Cycle Callback-Methoden onResume() und onCreate() überschreiben, um in ihnen die Verbindung zur Datenbank korrekt zu verwalten.

Weiterhin werden wir einen OnClickListener für den Add-Button registrieren und so auf Benutzereingaben reagieren. Durch einen Klick auf den Button sollen die in die EditText-Felder eingetragenen Werte in die Tabelle der SQLite Datenbank geschrieben werden.

Abschließend werden wir unsere SQLite App ausführen und testen, dabei werden wir erstmals echte Werte in die Datenbank über die grafische Benutzeroberfläche eintragen.

Nun wünschen wir euch viel Spaß bei Teil 5 unseres Android SQLite Datenbank Tutorials. Los geht’s!

1. Der Lebenszyklus einer Activity in Android

Android Apps Programmieren Online-Kurs

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Eine Android App besteht meist aus mehreren Activities, die lose miteinander verbunden sind. Wenn eine neue Activity gestartet wird, ändert die aktuelle Activity ihren Zustand und wird gestoppt.

Die neu gestartete Activity erhält den Fokus und wird ganz oben auf dem Back Stack abgelegt. Die gestoppte Activity befindet sich direkt darunter.

Der Zustand der gestoppten Aktivität bleibt im Android System erhalten, da die gestoppte Activity bereits auf dem Back Stack abgelegt war und nur eine Position nach hinten verschoben wurde.

Drückt der Benutzer jetzt den Back-Button, wird die gestartete Aktivität vom Back Stack entfernt und zerstört. Zeitgleich wird die vorherige, gestoppte Aktivität wieder fortgesetzt (restarted) und erhält den Fokus. Der Back Stack arbeitet nach dem Last in, First out-Prinzip.

Wenn eine Activity gestoppt wird, weil eine neue Activity startet, wird sie über die Zustandsänderung durch die Lifecycle-Callbacks informiert. In Android sind mehrere Callback-Methoden implementiert, die bei einer Zustandsänderung der Aktivität aufgerufen werden.


Jede Callback-Methode bietet die Gelegenheit bestimmte, notwendige Arbeiten auszuführen, bevor die Zustandsänderung in Kraft tritt. Für uns sind die beiden Callback-Methoden onResume() und onPause() für die Verwaltung der SQLite Datenbankverbindung besonders wichtig.

Im Folgenden werden wir den Android Lifecycle mit seinen Callback-Methoden vorstellen und anschließend die für unsere SQLite App relevanten Lifecycle-Callbacks besprechen.

1.1 Der Android Lifecycle von Activities und Fragmenten

Neben Activities durchlaufen auch Fragmente einen wohldefinierten Lebenszyklus. Wir werden nun kurz beide Zyklen vorstellen und dabei besonders auf den Activity Lifecycle eingehen. Falls ihr tiefer in die Materie eintauchen möchtet, solltet ihr den theoretischen Teil des folgenden Beitrags in Ruhe lesen: Der Activity und Fragment Lifecycle in Android.

Wenn eine Activity ihren aktuellen Zustand verlässt und einen neuen Zustand betritt, wird sie über verschiedene Callback-Methoden über die Zustandsänderung informiert. Alle Callback-Methoden können überschrieben werden, wodurch entsprechend auf die Zustandsänderung reagiert werden kann.

In Android sind die folgenden Lifecycle-Callbacks für Activities definiert:

  • onCreate(Bundle savedInstanceState) – Die Activity wird erstellt. Hier beginnt der Lebenszyklus.
  • onStart() – Die Activity ist kurz davor sichtbar zu werden.
  • onResume() – Die Activity ist sichtbar geworden und hat den Benutzer-Fokus.
  • onPause() – Eine andere Activity erhält den Fokus. Diese Activity wird pausiert.
  • onStop() – Die Activity ist nicht mehr sichtbar und wird nun gestoppt.
  • onRestart() – Die Activity wird neu gestartet. Als Nächstes wird onStart() aufgerufen.
  • onDestroy() – Die Activity wird zerstört werden. Hier endet der Lebenszyklus.
  • onSaveInstanceState(Bundle outState) – Die Activity wird in den nächsten Momenten gestoppt. Jetzt kann der aktuelle Zustand als Sammlung von Key-Value Paaren gespeichert werden.
  • onRestoreInstanceState(Bundle savedInstanceState) – Die Activity wird wieder hergestellt, nachdem sie aufgrund von Speichermangel zerstört wurde. Dieser Callback wird nur aufgerufen, wenn das Bundle nicht null ist. Der Aufruf erfolgt unmittelbar nach onStart().

Die folgende Abbildung verdeutlicht in welcher Reihenfolge die Lifecycle-Callbacks aufgerufen werden:

android activity lifecycle

Die Callback-Methoden des Activity Lifecycle in Android

Die Rechtecke repräsentieren die Callback-Methoden, die von euch implementiert werden können, um notwendige Operationen bei Zustandsänderungen durchzuführen.

Für unsere SQLite App sind die folgenden beiden Callback-Methoden relevant:

  • onResume() – Die Activity ist sichtbar geworden und hat den Benutzer-Fokus. Hier werden wir die Verbindung zur SQLite Datenbank herstellen.
  • onPause() – Die Activity wird pausiert. Hier werden wir die Verbindung zur SQLite Datenbank trennen. Diese Callback-Methode ist die letzte garantiert aufgrufene Methode bevor eine Activity zerstört werden kann. Normalerweise werden die nachfolgenden Callbacks auch noch ausgeführt. Dies kann aber nicht garantiert werden, bspw. bei akutem Speichermangel.

Somit wissen wir nun welche Lifecycle-Callbacks unserer MainActivity wir überschreiben werden und auch warum wir dies tun.

Zur Vollständigkeit gehen wir nun auch kurz auf den Lebenszyklus von Fragmenten in Android ein. Für unsere App ist dies nicht relevant, da sie nur über eine Activity und keine Fragmente verfügt.

android fragment lifecycle

Die Callback-Methoden des Fragment Lifecycles in Android

Der Quellcode eines Fragments ist dem einer Activity sehr ähnlich. Ein Fragment besitzt die gleichen Callback-Methoden wie eine Activity (bspw. onCreate(), onStart(), onPause(), onStop() und onDestroy()).

Zusätzlich verfügt ein Fragment über einige weitere Callback-Methoden, wie onAttach(), onCreateView(), onActivityCreated(), onDestroyView() und onDetach().

Da es so viele Gemeinsamkeiten zwischen Activities und Fragmenten gibt, kann in vielen Fällen Code von der Callback-Methode der Activity in die entsprechende Callback-Methode des Fragments umgelagert werden, wenn eine Android App auf Fragmente umgestellt werden soll.

Der Hauptunterschied im Lebenszyklus von Activities und Fragmenten ist die Art und Weise wie sie jeweils in dem entsprechenden Back Stack angelegt werden.

Eine gestoppte Activity wird auf den Activities Back Stack gelegt, welcher vom Android System verwaltet wird. Der User kann mit dem Back-Button zurück in die gestoppte Activity navigieren.

Ein Fragment wird jedoch auf einen speziellen Back Stack gelegt, welcher von der übergeordneten Activity verwaltet wird. Dies ist aber nur der Fall, wenn es mit dem Aufruf von addToBackStack() beim Entfernen des Fragments explizit so angewiesen wurde.

Auf der rechten Seite ist der Fragment Lifecycle in Android dargestellt. Wie zu erkennen ist, sind die meisten Callback-Methoden auch im Activity Lebenszyklus vorhanden.

Soviel zu dem spannenden Thema Android Lifecycle.

Kommen wir nun zu den relevanten Callbacks-Methoden onResume() und onPause() unserer MainActivity-Klasse zurück, auf die wir im nächsten Unterabschnitt genauer eingehen werden.

1.2 Welche Lifecycle Callbacks sind für unsere SQLite App relevant

Es gibt viele Gründe Lifecycle-Callbacks in Android Apps zu verwenden. Oft werden die Callbacks genutzt um den Zustand der Membervariablen zu speichern und diesen später beim Erzeugen der Activity wieder herzustellen.

Auch das Abtasten von Sensordaten wird mit Hilfe der Callbacks gezielt aktiviert und deaktiviert, um den Akku zu schonen.

Wir werden die Lifecycle-Callbacks verwenden, um die Verbindung zur SQLite Datenbank korrekt zu verwalten. Eine offene Verbindung zur Datenbank wird von uns nur benötigt, wenn unsere MainActivity den Benutzer-Fokus besitzt. Also sich in dem Resumed-Zustand befindet.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Eine Activity kann in den folgenden drei Zuständen existieren:

  • Resumed – Die Activity ist im Bildschirmvordergrund und besitzt den Benutzer-Fokus.
  • Paused – Eine andere Activity ist im Bildschirmvordergrund und besitzt den Benutzer-Fokus, verdeckt jedoch die überlagerte Activity nicht komplett. Ein Settings-Dialog bspw. verdeckt die Activity nur teilweise. Im Paused-Zustand ist eine Activity vollständig intakt (alive). Das Activity-Objekt wird im Speicher gehalten und alle Zustands- und Memberinformationen bleiben erhalten. Die pausierte Activity kann jedoch vom Android System in Situationen mit extrem niedrigem Speicher zerstört (killed) werden.
  • Stopped – Die Activity wird von einer anderen Activity vollständig verdeckt und befindet sich nun um Bildschirmhintergrund. Auch eine gestoppte Activity ist intakt. Das Activity-Objekt wird im Speicher gehalten und alle Zustands- und Memberinformationen bleiben erhalten. Die Activity ist jedoch nicht mehr dem Window Manager zugewiesen. In Situationen mit extrem wenig verfügbarem Speicher kann eine gestoppte Activity vom Android System zerstört werden.

Eine pausierte oder gestoppte Activity kann jederzeit vom Android System zerstört werden. Dies geschieht entweder durch Aufrufen der finish()-Methode oder durch direktes Beenden ihres Prozesses. Wird eine zerstörte Activity wieder geöffnet, muss sie komplett neu erstellt werden.

Sobald die MainActivity den Benutzer-Fokus verliert, werden wir die Verbindung zur SQLite Datenbank schließen. Die Verbindung bleibt so lange geschlossen, bis die Activity den Benutzer-Fokus wieder zurück erhält.

Die Operationen für das Öffnen und Schließen der Datenbankverbindung müssen daher in den folgenden Callback-Methoden stattfinden:

onResume()
Wird aufgerufen, kurz bevor die Activity mit dem Benutzer interagiert. Zu diesem Zeitpunkt ist die Activity ganz oben auf dem Activity Stack und empfängt die Benutzereingaben. In ihr werden wir die Verbindung zur SQLite Datenbank herstellen. Das Android System kann den App-Prozess nach dieser Methode nicht beenden. Der Methode folgt immer die onPause() Methode.


onPause()
Wird aufgerufen, kurz bevor das System eine andere Activity startet. In ihr sollten vorgenommene Änderungen gespeichert und Animationen beendet werden. Diese Vorhaben sollten unbedingt sehr schnell ausführbar sein, da die nächste Activity erst danach fortgesetzt wird. In dieser Methode werden wir die Verbindung zur SQLite Datenbank trennen. Nach dieser Methode kann das Android System den App-Prozess direkt beenden, sollte dies aufgrund von Speichermangel erforderlich sein. Der Methode folgt die onResume() Methode, wenn die Activity wieder in den Vordergrund rückt bzw. die onStop() Methode, wenn die Activity verdeckt wird.


Jetzt wissen wir welche Callback-Methoden wir für das Verwalten der SQLite Datenbankverbindung verwenden werden. In Abschnitt 3 werden wir Anweisungen aus der onCreate() Methode in die beiden Callback-Methoden auslagern.

Doch bevor wir dies tun werden, möchten wir noch kurz besprechen wie Benutzereingaben in Android erfasst und verarbeitet werden.

2. Benutzereingaben erfassen und auf Klicks reagieren

Mit unserer Einkaufslisten-App sollen die User in der Lage sein über die beiden EditText-Felder Eingaben vorzunehmen und diese mit einem Klick auf den Add-Button in die SQLite Datenbank eintragen zu lassen.

Um dies zu realisieren, müssen wir zwei neu Funktionen unserer App hinzufügen. Unsere SQLite App muss das Klicken auf den Add-Button erkennen und die in den EditText-Feldern eingetragenen Werte auslesen können.

Ob ein Button geklickt wurde, wird mit einem OnClickListener überprüft.

Das Auslesen der EditText-Felder wird mit Hilfe der Ressourcen-Datei R von Android bewerkstelligt, über welche wir die entsprechenden Widget-Objekte finden und deren Inhalte anschließend auslesen können.

2.1 Wie liest man eine EditText-Feld in Android aus?

Das Auslesen eines EditText-Feldes ist sehr einfach. Wir müssen dazu nur seine ID kennen, über die wir an das zugehörige EditText-Objekt gelangen. Der Inhalt des Feldes kann mit der getText() Methode ausgelesen werden, die auf dem entsprechenden EditText-Objekt aufgerufen wird.

Der folgende Quellcode zeigt wie ein EditText-Feld ausgelesen und dessen Inhalt weiterverarbeitet wird:

...

EditText editTextQuantity = (EditText) findViewById(R.id.editText_quantity);
String quantityString = editTextQuantity.getText().toString();

if(TextUtils.isEmpty(quantityString)) {
    editTextQuantity.setError(getString(R.string.editText_errorMessage));
    return;
}

int quantity = Integer.parseInt(quantityString);
editTextQuantity.setText("");

...

Mit der Anweisung in Zeile 3 suchen wir nach der Instanz des EditText-Feldes mit Hilfe der findViewById() Methode. Diese erwartet als Argument die ID des EditText-Widgets. Welche ID dieses Widget in unserer Hierarchie von View-Objekten besitzt, erfahren wir über die Ressourcen-Datei R. Das Anlegen dieser ID haben durch Definieren des EditText-Widgets in der Layoutdatei activity_main.xml veranlasst.

Hinweis: Die Ressourcen-Datei R ist eine von Android Studio generierte Java-Klasse, die sehr viele Konstanten enthält. Diese Konstanten werden in inneren Klassen verwaltet. So gibt es bspw. die innere Klasse id in der die IDs unserer App als int-Konstanten abgelegt sind. Darin befindet sich in unserem Fall auch eine Konstante mit dem Bezeichner editText_quantity vom Datentyp int. Ihr wurde automatisch ein int-Wert von Android Studio zugewiesen. Mit R.id.editText_quantity können wir den Wert dieser Konstanten auslesen. Übergeben wir diesen int-Wert der findViewById() Methode, erhalten wir das zugehörige View-Objekt als Rückgabewert. In unserem Fall ist dies ein EditText-Widget.

Nachdem wir eine Referenz auf das EditText-Objekt erhalten haben, lesen wir in Zeile 4 den Inhalt des Textfeldes aus. Der ausgelesene Wert ist immer vom Datentyp String, auch wenn in das Textfeld nur Zahlen eingegeben werden sollen.

Mit den Zeilen 6 bis 9 prüfen wir, ob der ausgelesene Wert leer ist. Falls ja, informieren wir den User mittels Fehlermeldung über die Falscheingabe und springen zurück zur aufrufenden Methode.

Falls der ausgelesene Wert nicht leer ist, wandeln wir ihn mit der Anweisung aus Zeile 11 in einen Integer-Wert um. Anschließend setzen wir den Inhalt des Textfeldes mit der Anweisung aus Zeile 12 zurück.

Mit diesen einfachen Schritten sind wir in der Lage ein EditText-Feld auszulesen, den Inhalt zu überprüfen und das Feld schließlich wieder zu leeren. Den ausgelesenen Wert können wir anschließend in die SQLite Datenbank eintragen.

2.2 Wie erkennt man, dass ein Button angeklickt wurde?

Auch das Erkennen von und Reagieren auf Button-Klicks ist in Android sehr einfach zu implementieren. Man benötigt dazu eine Referenz auf das Button-Objekt. Diese kann über die Ressourcen-Datei R und die findViewById() Methode angefragt werden.

Hat man die Referenz auf das Button-Objekt erhalten, muss nur noch ein OnClickListener für dieses registriert werden.

Der folgende Quellcode zeigt diese beiden Schritte beispielhaft:

...

Button buttonAddProduct = (Button) findViewById(R.id.button_add_product);

buttonAddProduct.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

    // Auslesen der Textfelder
    // Speichern der ausgelesenen Werte in die SQLite Datenbank
    // Aktualisieren der Anzeige

    }
});

...

In Zeile 3 fragen wir die Referenz auf das Button-Objekt an. Wir übergeben dazu der Methode findViewById() die ID des Buttons. Die ID haben wir in der Layoutdatei activity_main.xml für das Button-Widget definiert.

Für das Button-Objekt registrieren wir dann mit den Zeilen 5 bis 14 einen OnClickListener. Der OnClickListener ist ein Interface und besitzt genau eine abstrakte Methode, die onClick() Methode, welche wir implementieren müssen.

Die onClick() Methode wird automatisch über einen in der View-Klasse implementierten Callback aufgerufen, sobald der Button angeklickt wurde. Somit können wir in der onClick() Methode erfassen, dass der Button geklickt wurde und entsprechend darauf reagieren.

In der onClick() Methode werden wir daher die Inhalte der beiden Textfelder unserer SQLite App auslesen, ihre Werte in die Datenbank speichern und anschließend den ListView aktualisieren.

Wenn ihr nicht genau wisst was ein Interface in Java ist, könnt ihr in unserem Java-Kurs mehr darüber erfahren.

Jetzt sind wir am Ende des theoretischen Teils dieser Lektion angekommen und sind bereit das erlangte Wissen in unser SQLite Projekt einzubringen. Dazu werden wir im nächsten Abschnitt die MainActivity-Klasse unserer SQLite App umstrukturieren und erweitern.

3. Erweitern der MainActivity unserer SQLite App

Nun werden wir die MainActivity-Klasse umstrukturieren und um eine neuen Methode erweitern. Über die MainActivity sollen die Benutzereingaben erfasst und in die SQLite Datenbank gespeichert werden.

Um dies zu realisieren, nehmen wir die folgenden vier Änderungen am Quellcode der Klasse MainActivity vor:

  1. Einfügen der Import-Anweisungen – Zuerst importieren wir die benötigten Klassen.
  2. Überschreiben der Lifecycle-Callbacks – Wir werden die beiden Callback-Methoden onResume() und onPause() überschreiben und mit ihnen die Verbindung zur SQLite Datenbank verwalten.
  3. Überarbeiten der onCreate() Methode – Hier werden wir einige Anweisungen löschen, die entweder nur Testzwecken dienten oder in der Zwischenzeit in die beiden neuen Callback-Methoden ausgelagert wurden. Außerdem werden wir von hier die neue Methode activateAddButton() aufrufen.
  4. Definieren der activateAddButton() Methode – In dieser Methode registrieren wir einen OnClickListener für den Add-Button. Über den Listener werden wir die Textfelder auslesen und ihre Inhalte in die SQLite Datenbank schreiben, sobald der Button geklickt wurde.

Hinweis: Wir werden jetzt die Arbeitsschritte der Reihe nach ausführen. Sollte etwas unklar sein, könnt ihr im Anschluss daran den gesamten Quellcode der MainActivity-Klasse in Ruhe analysieren und direkt erkennen, an welcher Stelle welcher Code-Block eingefügt werden muss.

Nun beginnen wir mit dem ersten Arbeitsschritt.

3.1 Einfügen der Import-Anweisungen

Wir öffnen nun die Klassendatei MainActivity.java in dem Editor von Android Studio. Die Klassendatei befindet sich im Package-Ordner de.codeyourapp.shoppinglist unseres Projekts.

Anschließend fügen wir den folgenden Quellcode unter den bereits vorhandenen Import-Anweisungen ein:

MainActivity.java

import android.view.inputmethod.InputMethodManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

Die fünf Klassen machen wir mittels Import-Anweisungen innerhalb der Klasse MainActivity sichtbar, so dass wir sie ohne den Namen ihres Packages verwenden können.

Die Klasse InputMethodManager benötigen wir für das Einklappen des Soft Keyboards nach der Eingabe des Listeneintrags. Mit der Klasse TextUtils prüfen wir, ob den Benutzer eine leere Eingabe getätigt hat. Die Klassen View, Button und EditText benötigen wir für die Arbeit mit den User Interface-Elementen.

3.2 Überschreiben der relevanten Lifecycle-Callback Methoden

In dem zweiten Arbeitsschritt werden wir die beiden Callback-Methoden onResume() und onPause() überschreiben und dabei Code aus der onCreate() Methode in diese beiden neuen Methoden auslagern.

In der onResume() Methode werden wir die Verbindung zu unserer SQLite Datenbank herstellen, indem wir die Datenquelle öffnen. Anschließend lassen wir alle Inhalte der SQLite Datenbank in dem ListView anzeigen. In der onPause() Methode lassen wir die Verbindung zur SQLite Datenbank wieder schließen.

Wir fügen nun den folgenden Quellcode in den Methodenbereich der MainActivity.java-Klasse direkt nach der onCreate() Methode ein:

An dieser Stelle endet der freie Inhalt dieser Lektion. Wir hoffen, sie hat dir bis hierher gefallen! Du kannst sie im geschützten Bereich von ProgrammierenLernenHQ fortsetzen, in welchem sich alle Lektionen unserer Android Online-Kurse befinden.

Unsere Android Kurse bestehen aus insgesamt 43 großen Lektionen und sind unterteilt in 13 frei zugängliche und 30 Premium-Lektionen. Die Premium-Lektionen befinden sich in dem geschützten Bereich und sind nur für Käufer unseres Android Online-Kurs Gesamtpaket zugänglich.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813 An dieser Stelle endet der freie Inhalt dieser Lektion. Wir hoffen, sie hat dir bis hierher gefallen! Du kannst sie durch Kauf unseres Android Online-Kurs Gesamtpakets freischalten.

In unserem Android Online-Kurs Gesamtpaket befinden sich 43 große Lektionen, in denen wir dir schrittweise zeigen, wie voll funktionstüchtige Android Apps programmiert werden.

Diese Lektion ist Teil unseres Android Gesamtpakets. Insgesamt sind unsere Online-Kurse unterteilt in 13 frei zugängliche und 30 Premium-Lektionen.

Die Premium-Lektionen befinden sich in dem geschützten Bereich und sind nur für Käufer des Android Online-Kurs Gesamtpakets zugänglich.



Welche Inhalte befinden sich im Android Online-Kurs Gesamtpaket?

  • Das Gesamtpaket enthält alle Android Online-Kurse von ProgrammierenLernenHQ.
  • Im Paket enthalten ist unser großer Android Apps Programmieren Online-Kurs. Er ist unser Hauptkurs und besteht aus 35 großen Lektionen. Die Grundlagen der Android App Entwicklung praxisnah und verständlich zu lehren, ist das Hauptziel des Android Apps Programmieren Kurses.
  • Im Paket enthalten ist auch unser SQLite Datenbank App Programmieren Online-Kurs. Dieser Spezialkurs besteht aus 8 großen Lektionen und ist als weiterführender Kurs konzipiert worden. Der Kurs schließt an unseren Android Apps Programmieren Hauptkurs an und widmet sich dem speziellen Thema der SQLite Datenbanken.
  • Durch den Kauf erhältst du unbegrenzten Zugang zu allen Inhalten unseres Android Online-Kurs Gesamtpakets. Wir werden in Zukunft weitere Lektionen hinzufügen. Auch auf alle zukünftigen Lektionen erhältst du vollen Zugriff.

Wir hoffen, Dich bald als neuen Kursteilnehmer unserer Android Online-Kurse begrüßen zu dürfen!

Einmal kaufen und dadurch zeitlich unbegrenzten Zugriff auf alle Inhalte unseres Android Online-Kurs Gesamtpakets erhalten.



Hinweis: Der untere Quellcode ist Teil des geschützten Bereichs von ProgrammierenLernenHQ. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte.
Erfahre mehr über unsere Android Online-Kurse.

MainActivity.java

android_sqlite_table_mainactivity_blurry

Der Quellcode ist zu großen Teilen bereits bekannt, da er direkt aus der onCreate() Methode ausgeschnitten und in die Callback-Methoden eingefügt wurde.

Eine Besonderheit sind die Aufrufe der jeweiligen Super-Methoden in den Zeilen 3 und 14. Wird eine Lifecycle-Methode implementiert, muss unbedingt als Erstes die zugehörige Methoden-Implementierung der Basisklasse aufgerufen werden. Erst danach dürfen die eigenen Anweisung stehen.

3.3 Überarbeiten der onCreate() Methode der MainActivity-Klasse

Im dritten Arbeitsschritt überarbeiten wir die onCreate() Methode unserer MainActivity-Klasse. Wir werden von der onCreate() Methode aus nur noch das Datenquellen-Objekt anlegen und den Add-Button aktivieren lassen.

Den Quellcode für das Öffnen und Schließen der Datenbankverbindung werden wir aus ihr entfernen, da wir diesen bereits im vorherigen Schritt in die beiden Lifecycle-Callbacks ausgelagert haben. Außerdem entfernen wir sämtlichen Testcode aus der onCreate() Methode.

Die onCreate() Methode der MainActivity.java besteht nun aus folgenden Quellcode:

Hinweis: Der untere Quellcode ist Teil des geschützten Bereichs von ProgrammierenLernenHQ. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte.
Erfahre mehr über unsere Android Online-Kurse.

MainActivity.java

android_sqlite_table_mainactivity_blurry

In Zeile 9 wird die activateAddButton() Methode, durch die der Add-Button aktiviert wird, aufgerufen. Da die Methode noch nicht von uns definiert wurde, wird sie im Editorfenster noch in roter Schrift angezeigt. Wir werden sie im nächsten Arbeitsschritt definieren und damit das Problem beheben.

3.4 Definieren der activateAddButton() Methode

Kommen wir nun zum wichtigsten Arbeitsschritt dieser Lektion des Android SQLite Tutorials. Wir werden nun eine neue Methode definieren, mit der wir Klicks auf den Add-Button erfassen und entsprechend darauf reagieren.

Wie so etwas in Android implementiert wird, haben wir bereits weiter oben im theoretischen Teil besprochen. Jetzt ist es an der Zeit dies in die Praxis umzusetzen.

Wir fügen nun den folgenden Quellcode in den Methodenbereich der MainActivity.java Klasse direkt nach der showAllListEntries() Methode ein:

MainActivity.java

private void activateAddButton() {
  Button buttonAddProduct = (Button) findViewById(R.id.button_add_product);
  final EditText editTextQuantity = (EditText) findViewById(R.id.editText_quantity);
  final EditText editTextProduct = (EditText) findViewById(R.id.editText_product);

  buttonAddProduct.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

      String quantityString = editTextQuantity.getText().toString();
      String product = editTextProduct.getText().toString();

      if(TextUtils.isEmpty(quantityString)) {
        editTextQuantity.setError(getString(R.string.editText_errorMessage));
        return;
      }
      if(TextUtils.isEmpty(product)) {
        editTextProduct.setError(getString(R.string.editText_errorMessage));
        return;
      }

      int quantity = Integer.parseInt(quantityString);
      editTextQuantity.setText("");
      editTextProduct.setText("");

      dataSource.createShoppingMemo(product, quantity);

      InputMethodManager inputMethodManager;
      inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
      if(getCurrentFocus() != null) {
        inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
      }

      showAllListEntries();
    }
  });

}

Mit den Anweisungen in den Zeilen 2 bis 4 fragen wir die Referenzen zu den Widget-Objekten an. Diese sind der Add-Button und die beiden EditText-Felder.

Den OnClickListener registrieren wir mit den Zeilen 6 bis 36 für das Button-Objekt. Dazu verwenden wir die Methode setOnClickListener(), die wir auf dem Button-Objekt aufrufen und ihr ein OnClickListener-Objekt übergeben.

Für das Erzeugen des OnClickListener-Objekts implementieren wir das View.OnClickListener-Interface mit Hilfe einer anonymen Klasse. Dabei wird die onClick() Callback-Methode des Interfaces überschrieben.

In der onClick() Methode lesen wir mit den Zeilen 10 und 11 die beiden Textfelder aus.

Mit den if-Anweisungen in den Zeilen 13 bis 20 prüfen wir, ob in dem jeweiligen Textfeld etwas eingetragen wurde. Falls ein Feld leer ist, lassen wir über die Methode setError() eine Fehlermeldung vom jeweiligen Textfeld ausgeben und beenden die onClick() Methode.

Den Wert des EditText-Feldes editTextQuantity wandeln wir in Zeile 22 in einen Integer-Wert um, da die Werte der Textfelder nur als String-Objekte vorliegen. Mit den Anweisungen in den Zeilen 23 und 24 setzen wir den Wert der Textfelder zurück und löschen damit die eingetragenen Werte.

Anschließend speichern wir die beiden ausgelesenen Werte mit der Anweisung aus Zeile 26 in die Android SQLite Datenbank ab. Die Arbeit überlassen wir unserer Datenquelle dataSource. Wir müssen ihrer Methode createShoppingMemo() nur die ausgelesenen Werte übergeben, den Rest übernimmt sie für uns.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Mit den Anweisungen in den Zeilen 28 bis 32 lassen wir das Soft Keyboard verschwinden, so dass unsere Einkaufsliste komplett zu sehen ist. Anschließend geben wir alle Einträge der SQLite Datenbank mit Hilfe des ListViews auf dem Display aus, dazu rufen wir die showAllListEntries() Methode in Zeile 34 auf.

Den Code für das Verstecken des Soft Keyboards haben wir aus einer Antwort bei StackOverflow entnommen. Ihr könnt ihn hier: How to hide soft keyboard on android after clicking outside EditText nachlesen.

3.5 Der komplette Quellcode der MainActivity-Klasse

Nun haben wir alle Änderungen an der MainActivity-Klasse vorgenommen. Mit dem eingefügtem Quellcode reagieren wir auf Benutzereingaben und speichern die eingetragenen Werte in der SQLite Datenbank ab.

In dem unten angegebenen Quellcode ist die gesamte MainActivity-Klasse zur Kontrolle für euch aufgeführt. Die neu eingefügten bzw. überarbeiteten Zeilen sind markiert worden.

In Android Studio sollte die MainActivity.java Klassendatei nun wie folgt aussehen:

Hinweis: Der untere Quellcode ist Teil des geschützten Bereichs von ProgrammierenLernenHQ. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte.
Erfahre mehr über unsere Android Online-Kurse.

android_sqlite_lektion5_blurry

Der obere Quellcode ist Teil des geschützten Bereichs von ProgrammierenLernenHQ. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte.
Erfahre mehr über unsere Android Online-Kurse.

In der oberen Abbildung ist die überarbeitete MainActivity.java Klassendatei dargestellt. Der bisherige Quellcode wurde an vier Stellen (Markierung A, B, C und D) erweitert bzw. überarbeitet.

Welche Bedeutung der jeweilige Code-Block besitzt, ist in der unteren Liste angegeben:

  1. A – Die benötigten Import-Anweisungen zum Sichtbarmachen der Klassen bzw. Interfaces InputMethodManager, TextUtils, View, Button und EditText.
  2. B – Die onCreate() Methode wurde um den Testcode bereinigt. Durch sie wird nun nur noch das Layout unserer App geladen, das Datenbank-Objekt angelegt und der Add-Button aktiviert.
  3. C – Die neu angelegten Callback-Methoden onResume() und onPause(), durch die wir die Verbindung zur SQLite Datenbank verwalten lassen.
  4. D – Die Methode activateAddButton(), durch die wir den OnClickListener für den Add-Button registrieren und die Inhalte der beiden Textfelder auslesen und in die Datenbank schreiben lassen.

Mit diesen Änderungen im Quellcode der MainActivity-Klasse haben wir unsere SQLite App um eine sehr nützliche Funktion erweitert. Wir können jetzt selbst echte Daten in die SQLite Datenbank unter Zuhilfenahme der Datenquelle schreiben.

Im nächsten Abschnitt werden wird die grafische Benutzeroberfläche unserer SQLite App testen und erstmals sinnvolle Werte in die Einkaufsliste über die Widget-Elemente eintragen.

4. Starten und Testen unserer SQLite App

Wir werden nun unserer Android App auf einem Android Virtual Device im Emulator ausführen lassen und überprüfen, ob Einträge über das User Interface in die SQLite Datenbank gespeichert werden können.

Hinweis: Wenn ihr Probleme beim Ausführen der App im Android Emulator oder auf einem Android Gerät haben solltet, könnt ihr unseren großen Android Apps Programmieren Kurs als Hilfe nutzen. Darin zeigen wir, wie eine Android App im Emulator oder auf einem physikalischen Android Gerät ausgeführt wird.

Unsere App starten wir dazu wie gewohnt über den Run > Run 'app' Menüeintrag, den wir über die obere Menüleiste erreichen.

Unsere SQLite App sollte jetzt auf dem Android Gerät gestartet worden sein. Die grafische Benutzeroberfläche der Anwendung hat sich auch diesmal nicht geändert, daher sieht auf dem Gerät alles genau so aus wie in der vorherigen Lektion.

Hinweis: Das Emulator-Fenster mit dem darin laufenden Android Virtual Device muss für die nächsten Arbeitsschritte geöffnet bleiben. Zudem muss in dem AVD unsere eigene App ausgeführt werden. Sollte dies nicht der Fall sein, muss die App erneut im Emulator gestartet werden.

Um die Log-Meldungen zu überprüfen, öffnen wir in Android Studio das Logcat Tool Window während unsere App auf dem AVD im Emulator ausgeführt wird.

Dazu führen wir die folgenden Schritte aus:

  1. Wir öffnen das Logcat Tool Window mit einem Klick auf den Logcat-Tab am unteren Bildschirmrand.
  2. Anschließend wählen wir Emulator Nexus_9 als AVD in der Drop-Down Liste aus.
  3. Nun wählen wir unsere App de.codeyourapp.shoppinglist in der Liste rechts daneben aus.
  4. Danach stellen wir die Prioritätsstufe auf Verbose ein.
  5. Und geben in das anschließende Suchfeld MainActivity|ShoppingMemo als Suchbegriff ein.
  6. Dann wählen wir den Eintrag Show only selected application in Liste ganz rechts aus.
  7. Nun drücken wir den Back Button auf dem Android Virtual Device im Emulator und lassen dadurch unsere App beenden. Dabei wird die MainActivity vom Android System zerstört.
android_sqlite_button_logcat

Überprüfen der Log-Meldungen unserer App im Logcat Tool Window von Android Studio

Uns werden die folgenden Log-Meldungen ausgegeben:

01: MainActivity﹕ Das Datenquellen-Objekt wird angelegt.
02: ShoppingMemoDataSource﹕ Unsere DataSource erzeugt jetzt den dbHelper.
03: ShoppingMemoDbHelper﹕ DbHelper hat die Datenbank: shopping_list.db erzeugt.
04: MainActivity﹕ Die Datenquelle wird geöffnet.
05: ShoppingMemoDataSource﹕ Eine Referenz auf die Datenbank wird jetzt angefragt.
06: ShoppingMemoDataSource﹕ Datenbank-Referenz erhalten. Pfad zur Datenbank: /data/user/0/de.codeyourapp.shoppinglist/databases/shopping_list.db
07: MainActivity﹕ Folgende Einträge sind in der Datenbank vorhanden:
08: ShoppingMemoDataSource﹕ ID: 1, Inhalt: 2 x Testprodukt
09: ShoppingMemoDataSource﹕ ID: 2, Inhalt: 2 x Testprodukt
10: ShoppingMemoDataSource﹕ ID: 3, Inhalt: 2 x Testprodukt
11: ShoppingMemoDataSource﹕ ID: 4, Inhalt: 2 x Testprodukt
12: ShoppingMemoDataSource﹕ ID: 5, Inhalt: 2 x Testprodukt
13: MainActivity﹕ Die Datenquelle wird geschlossen.
14: ShoppingMemoDataSource﹕ Datenbank mit Hilfe des DbHelpers geschlossen.

Die erste Log-Meldung ist neu hinzugekommen und informiert uns darüber, dass eine Instanz der Datenqelle in der MainActivity angelegt wurde. Alle anderen Meldungen sind uns bereits bekannt. Anhand der Log-Meldungen können wir darauf schließen, dass unsere SQLite App auch nach den Umstrukturierungen der MainActivity-Klasse noch wie erwartet reagiert.

Als Nächstes deinstallieren wir die Anwendung von unserem Android Gerät, dadurch wird automatisch auch die SQLite Datenbank der App gelöscht.

Danach starten wir unsere Android App wieder wie gewohnt über den Run > Run ‚app‘ Menüeintrag, den wir über die obere Menüleiste in Android Studio erreichen.

Daraufhin wird unsere App erneut auf dem AVD installiert und anschließend gestartet. Dabei wird auch automatisch eine neue SQLite Datenbank-Datei angelegt wird.

Danach schreiben wir erstmals Einträge über die Benutzeroberfläche unserer Android App in die Tabelle der SQLite Datenbank. Das Ergebnis können wir in der unteren Abbildung betrachten, sie zeigt unsere SQLite App mit fünf selbst erstellten Einträgen:

android_sqlite_button_avd

In unsere SQLite Datenbank App können nun echte Einträge geschrieben werden

Wie zu erkennen ist, funktioniert unsere App wie erwartet. Die über die beiden Textfelder eingetragenen Werte werden in die Tabelle der SQLite Datenbank als Datensätze gespeichert und mit Hilfe des ListViews auf dem Android Gerät wieder ausgegeben.

Ein Video veranschaulicht die Funktion der SQLite App aber viel besser als ein Bild. Daher haben wir eine kleine Funktionspräsentation unserer SQLite App in Form eines Videos erstellt.

4.1 Video – Funktionspräsentation unserer SQLite App

In dem unteren Video haben wir einige Werte mit Hilfe der grafischen Benutzeroberfläche unserer Android App in die SQLite Datenbank eingetragen. In dem Video ist außerdem zu sehen, wie unsere SQLite App auf Fehleingaben reagiert.

Jetzt ist es möglich die Einkaufslisten-App sinnvoll zu nutzen. Leider gibt es noch ein Problem. Die Einträge lassen sich nicht über das User Interface löschen. Somit ist unsere SQLite App noch nicht vollständig.

Daher werden wir in der nächsten Lektion unsere Android App um eine Lösch-Funktion erweitern, mit deren Hilfe die Einträge komfortabel aus der SQLite Datenbank entfernt werden können.

Zusammenfassung

In dieser Lektion unseres Android SQLite Tutorials haben wir die Benutzeroberfläche mit Funktionen hinterlegt. Dazu haben wir einen OnClickListener für den Add-Button registriert, um damit auf Klicks der Benutzer reagieren zu können.

Von der implementierten onClick() Methode des OnClickListeners lassen wir die beiden EditText-Felder auslesen und die ausgelesenen Werte in der Tabelle unserer SQLite Datenbank ablegen. Zudem reagieren wir auf Fehleingaben, indem wir unseren Nutzern eine Fehlermeldung als Hinweis auf dem Android Gerät ausgeben.

Weiterhin haben wir in dieser Lektion die MainActivity umstrukturiert und zwei Lifecycle-Callbacks implementiert, über die wir die Verbindung zu der SQLite Datenbank verwalten. Mit der onResume() Methode stellen wir die Verbindung zur SQLite Datenbank her und mit der onPause() Methode schließen wir die Verbindung wieder.

Abschließend haben wir die neuen Funktionen unserer Android SQLite App überprüft und dadurch sichergestellt, dass die Datensätze korrekt in die Datenbank geschrieben und im ListView ausgeben werden.

Unsere Einkaufslisten-App kann jetzt schon genutzt werden. Es können Einträge über die Benutzeroberfläche in die SQLite Datenbank geschrieben und diese dann wieder im ListView der MainActivity auf dem Display ausgegeben werden.

Momentan fehlt aber noch die Möglichkeit Einträge wieder aus der SQLite Datenbank zu löschen. Dieses Problem werden wir uns in der nächsten Lektion des Android SQLite Tutorials vornehmen und unsere SQLite App um eine Lösch-Funktion erweitern.



Comments 9

  1. von allen Tutorielen auf Android bist du die erste und exzellente Person in ganz Deutschland.
    macht weiter so

    1. Post
      Author
  2. Kleiner Grammatikfehler in dem sonst perfekten Tutorial gefunden.
    *Die Verbindung zur SQLite Datenbank werden wie in der onPause() Methode wieder schließen.*

    … werden WIR in der ….

    1. Post
      Author
    2. Kleiner Logikfehler in dem sonst perfekten Kommentar gefunden.
      *Kleiner Grammatikfehler in dem sonst perfekten Tutorial gefunden.*

      … Kleiner TIPPFEHLER in dem….

  3. Zum Schaubild: Reihenfolge des Lifecycle-Callbacks
    Beim Zustand onPause() steht, dass eine andere App in den Vordergrund kommt. Damit ist aber nicht gemeint, dass die andere App tatsächlich auf dem Display dargestellt wird, sondern dass eine andere App gerade im Hintergrund die Hardwareressourcen benötigt?

    Denn für mich würde sich die Activity im onStop() befinden, wenn eine andere App in den Vordergrund kommt oder?

    Ich bin gerade dabei ein Projekt zu realisieren und ziemlich neu in Java-Programmierung und wollte fragen, ob es möglich ist, eine Erweiterung zu diesem Tutorial zu machen, in dem erklärt wird wie ich die Datenbank exportieren und importieren kann. Ich würde diese nämlich gern mit Freunden austauschen können und auf dem PC als Backup speichern.

    1. Post
      Author

      Hallo Daniel,

      damit ist gemeint, dass eine andere Activity gerade im Begriff ist in den Vordergrund zu rücken. Die onPause() Methode wird aufgerufen, kurz bevor das System eine andere Activity startet. In ihr sollten vorgenommene Änderungen gespeichert und Animationen beendet werden. Diese Vorhaben sollten unbedingt sehr schnell ausführbar sein, da die nächste Activity erst danach fortgesetzt wird.

      In diesem Beitrag Android Activity Lifecycle habe ich ausführlich darüber geschrieben.

      Ist eine andere Activity in den Vordergrund gerückt, befindet sich die eigene Activity im Stopped-Zustand. Die onStopped() Methode wurde bereits ausgeführt und hat die Activity in den Stopped-Zustand überführt.

      Die Erweiterungsidee mit dem Importieren und Exportieren der Datenbank habe ich mir notiert. Bei der Aktualisierung dieses Tutorials werde ich sie eventuell umsetzen. Dies sollte für einige Leser von Interesse sein.

      Viele Grüße, Chris

  4. Pingback: Android SQLite Tutorial - Teil 1: SQLite Projekt anlegen

  5. Pingback: Android SQLite Tutorial - Teil 2: SQLite Datenbank integrieren

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.