Willkommen zum Android SQLite Beispiel Tutorial. Android SQLite ist der bevorzugte Weg, um Daten für Android-Anwendungen zu speichern. Für viele Anwendungen ist SQLite das Rückgrat der Apps, ob es nun direkt oder über einen Drittanbieter-Wrapper verwendet wird. Unten sehen Sie die endgültige App, die wir heute unter Verwendung der Android SQLite-Datenbank erstellen werden.
Android SQLite
Android SQLite ist eine sehr leichtgewichtige Datenbank, die mit dem Android-Betriebssystem geliefert wird. Android SQLite kombiniert eine saubere SQL-Schnittstelle mit einem sehr geringen Speicherbedarf und anständiger Geschwindigkeit. Für Android ist SQLite „fest in“ die Android-Runtime integriert, sodass jede Android-Anwendung ihre eigenen SQLite-Datenbanken erstellen kann. Die native Android SQLite-API ist nicht JDBC, da JDBC für ein speicherbegrenztes Smartphone möglicherweise zu aufwendig ist. Sobald eine Datenbank erfolgreich erstellt wurde, befindet sie sich in data/data//databases/ und ist über den Android Device Monitor zugänglich. SQLite ist eine typische relationale Datenbank mit Tabellen (die aus Zeilen und Spalten bestehen), Indizes usw. Wir können unsere eigenen Tabellen erstellen, um die Daten entsprechend zu halten. Diese Struktur wird als Schema bezeichnet.
Android SQLite SQLiteOpenHelper
Android verfügt über Funktionen zum Umgang mit sich ändernden Datenbankschemas, die hauptsächlich von der Verwendung der Klasse SQLiteOpenHelper
abhängen. Die Klasse SQLiteOpenHelper ist darauf ausgelegt, zwei sehr häufig auftretende Probleme zu beseitigen.
- Wenn die Anwendung zum ersten Mal ausgeführt wird – Zu diesem Zeitpunkt haben wir noch keine Datenbank. Daher müssen wir die Tabellen, Indizes, Starterdaten usw. erstellen.
- Wenn die Anwendung auf ein neueres Schema aktualisiert wird – Unsere Datenbank wird immer noch das alte Schema der älteren Version der App haben. Wir haben die Möglichkeit, das Datenbankschema zu ändern, um es an die Bedürfnisse des restlichen Teils der App anzupassen.
SQLiteOpenHelper
fasst diese Logik zusammen, um eine Datenbank gemäß unseren Spezifikationen zu erstellen und zu aktualisieren. Dafür müssen wir eine benutzerdefinierte Unterklasse von SQLiteOpenHelper
erstellen, die mindestens die folgenden drei Methoden implementiert.
-
Konstruktor: Dieser nimmt den Kontext (z. B. eine Aktivität), den Namen der Datenbank, eine optionale Cursor-Fabrik (dazu kommen wir später) und eine Ganzzahl, die die Version des Datenbankschemas darstellt, entgegen (typischerweise beginnend mit 1 und später erhöht).
public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); }
-
onCreate(SQLiteDatabase db): Diese Methode wird aufgerufen, wenn keine Datenbank vorhanden ist und die App eine benötigt. Sie übergibt uns ein
SQLiteDatabase
-Objekt, das auf eine neu erstellte Datenbank zeigt und mit Tabellen und initialen Daten gefüllt werden kann. -
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion): Diese Methode wird aufgerufen, wenn die benötigte Schema-Version nicht mit der Schema-Version der Datenbank übereinstimmt. Sie übergibt uns ein SQLiteDatabase-Objekt sowie die alten und neuen Versionsnummern. Dadurch können wir die beste Methode zur Konvertierung der Datenbank vom alten Schema zum neuen ermitteln.
Wir definieren eine DBManager
-Klasse, um alle CRUD (Create, Read, Update und Delete)-Operationen auf der Datenbank durchzuführen.
Öffnen und Schließen der Android SQLite-Datenbankverbindung
Vor dem Durchführen von Datenbankoperationen wie dem Einfügen, Aktualisieren oder Löschen von Datensätzen in einer Tabelle öffnen Sie zunächst die Datenbankverbindung, indem Sie die Methode getWritableDatabase() wie unten gezeigt aufrufen:
public DBManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
return this;
}
Der dbHelper ist eine Instanz der Unterklasse von SQLiteOpenHelper
. Um eine Datenbankverbindung zu schließen, wird die folgende Methode aufgerufen.
public void close() {
dbHelper.close();
}
Einfügen eines neuen Datensatzes in eine Android SQLite-Datenbanktabelle
Der folgende Codeausschnitt zeigt, wie ein neuer Datensatz in der Android SQLite-Datenbank eingefügt wird.
public void insert(String name, String desc) {
ContentValues contentValue = new ContentValues();
contentValue.put(DatabaseHelper.SUBJECT, name);
contentValue.put(DatabaseHelper.DESC, desc);
database.insert(DatabaseHelper.TABLE_NAME, null, contentValue);
}
Content Values erstellt einen leeren Satz von Werten mit der angegebenen anfänglichen Größe. Wir werden die anderen Instanzwerte besprechen, wenn wir zum Codieren übergehen.
Aktualisieren eines Datensatzes in einer Android SQLite-Datenbanktabelle
Der folgende Code-Ausschnitt zeigt, wie ein einzelner Datensatz aktualisiert wird.
public int update(long _id, String name, String desc) {
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.SUBJECT, name);
contentValues.put(DatabaseHelper.DESC, desc);
int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null);
return i;
}
Android SQLite – Löschen eines Datensatzes
Es ist nur notwendig, die ID des zu löschenden Datensatzes wie unten gezeigt zu übergeben.
public void delete(long _id) {
database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null);
}
Android SQLite Cursor
A Cursor represents the entire result set of the query. Once the query is fetched a call to cursor.moveToFirst() is made. Calling moveToFirst() does two things:
- Es ermöglicht uns zu überprüfen, ob die Abfrage einen leeren Satz zurückgegeben hat (indem der Rückgabewert getestet wird)
- Es verschiebt den Cursor zum ersten Ergebnis (wenn der Satz nicht leer ist)
Der folgende Code wird verwendet, um alle Datensätze abzurufen:
public Cursor fetch() {
String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
Eine andere Möglichkeit, einen Cursor zu verwenden, besteht darin, ihn in einen CursorAdapter
einzuhüllen. Genau wie ArrayAdapter
Arrays anpasst, passt CursorAdapter
Cursor-Objekte an und stellt ihre Daten einem AdapterView
wie einem ListView
zur Verfügung. Springen wir zu unserem Projekt, das SQLite verwendet, um einige sinnvolle Daten zu speichern.
Beispielhaftes Projektstrukturschema von Android SQLite
In dieser Anwendung möchten wir Datensätze erstellen, die Ländernamen und ihre jeweiligen Währungen in Form einer ListView speichern. Wir decken alle oben besprochenen Funktionen ab.
Android SQLite Projektcode
Die Anwendung besteht aus 5 Klassen. Wir beginnen mit der Definition von DatabaseHelper, der eine Unterklasse von SQLiteOpenHelper ist, wie folgt: DatabaseHelper.java
package com.journaldev.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
// Tabellenname
public static final String TABLE_NAME = "COUNTRIES";
// Tabellenspalten
public static final String _ID = "_id";
public static final String SUBJECT = "subject";
public static final String DESC = "description";
// Datenbankinformationen
static final String DB_NAME = "JOURNALDEV_COUNTRIES.DB";
// Datenbankversion
static final int DB_VERSION = 1;
// Abfrage zum Erstellen der Tabelle
private static final String CREATE_TABLE = "create table " + TABLE_NAME + "(" + _ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + SUBJECT + " TEXT NOT NULL, " + DESC + " TEXT);";
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
Wie oben besprochen haben wir die Methoden onCreate()
und onUpgrade()
neben dem Konstruktor überschrieben. Wir haben den Datenbank- und Tabellennamen als JOURNALDEV_COUNTRIES.DB und COUNTRIES festgelegt. Die Indexspalte wird automatisch inkrementiert, wenn eine neue Zeile eingefügt wird. Die Spaltennamen für Land und Währung lauten „subject“ und „description“. Die Klasse DBManager ist der Ort, an dem der DatabaseHelper initialisiert und die CRUD-Operationen definiert werden. Hier ist der Code für diese Klasse: DBManager.java
package com.journaldev.sqlite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
public class DBManager {
private DatabaseHelper dbHelper;
private Context context;
private SQLiteDatabase database;
public DBManager(Context c) {
context = c;
}
public DBManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
return this;
}
public void close() {
dbHelper.close();
}
public void insert(String name, String desc) {
ContentValues contentValue = new ContentValues();
contentValue.put(DatabaseHelper.SUBJECT, name);
contentValue.put(DatabaseHelper.DESC, desc);
database.insert(DatabaseHelper.TABLE_NAME, null, contentValue);
}
public Cursor fetch() {
String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public int update(long _id, String name, String desc) {
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.SUBJECT, name);
contentValues.put(DatabaseHelper.DESC, desc);
int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null);
return i;
}
public void delete(long _id) {
database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null);
}
}
Die Klasse CountryListActivity.java
ist die Aktivität, die beim Start der Anwendung gestartet wird. Unten ist das Layout dafür definiert: fragment_emp_list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="1dp"
android:padding="10dp" >
</ListView>
<TextView
android:id="@+id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/empty_list_text" />
</RelativeLayout>
Hier wird eine ListView-Komponente definiert, um die in der Datenbank gespeicherten Datensätze einzuschließen. Anfangs ist die ListView leer, daher wird ein TextView verwendet, um das Gleiche anzuzeigen. CountryListActivity.java
package com.journaldev.sqlite;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
public class CountryListActivity extends ActionBarActivity {
private DBManager dbManager;
private ListView listView;
private SimpleCursorAdapter adapter;
final String[] from = new String[] { DatabaseHelper._ID,
DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
final int[] to = new int[] { R.id.id, R.id.title, R.id.desc };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_emp_list);
dbManager = new DBManager(this);
dbManager.open();
Cursor cursor = dbManager.fetch();
listView = (ListView) findViewById(R.id.list_view);
listView.setEmptyView(findViewById(R.id.empty));
adapter = new SimpleCursorAdapter(this, R.layout.activity_view_record, cursor, from, to, 0);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
// OnCLickListiner für Listenelemente
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView > parent, View view, int position, long viewId) {
TextView idTextView = (TextView) view.findViewById(R.id.id);
TextView titleTextView = (TextView) view.findViewById(R.id.title);
TextView descTextView = (TextView) view.findViewById(R.id.desc);
String id = idTextView.getText().toString();
String title = titleTextView.getText().toString();
String desc = descTextView.getText().toString();
Intent modify_intent = new Intent(getApplicationContext(), ModifyCountryActivity.class);
modify_intent.putExtra("title", title);
modify_intent.putExtra("desc", desc);
modify_intent.putExtra("id", id);
startActivity(modify_intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.add_record) {
Intent add_mem = new Intent(this, AddCountryActivity.class);
startActivity(add_mem);
}
return super.onOptionsItemSelected(item);
}
}
In dieser Aktivität wird das DBManager-Objekt aufgerufen, um CRUD-Operationen durchzuführen. Ein SimpleCursorAdapter wird definiert, um Elemente zur Liste aus den Abfrageergebnissen hinzuzufügen, die in einem Cursor-Objekt zurückgegeben werden. Bei einem Klick auf ein Listenelement wird ein Intent ausgeführt, um die Klasse ModifyCountryActivity zu öffnen. Das Menü enthält einen Eintrag, um einen neuen Datensatz aus der ActionBar hinzuzufügen. Hier wird erneut ein Intent ausgeführt, um die Klasse AddCountryActivity zu öffnen. Unten ist der Code von menu.xml
. menu.xml
<menu xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
tools:context="com.example.sqlitesample.MainActivity" >
<item
android:id="@+id/add_record"
android:icon="@android:drawable/ic_menu_add"
android:orderInCategory="100"
android:title="@string/add_record"
app:showAsAction="always"/>
</menu>
Das XML-Layout und der Code der Datei AddCountryActivity.java
sind unten definiert: activity_add_record.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp" >
<EditText
android:id="@+id/subject_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/enter_title" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/description_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/enter_desc"
android:inputType="textMultiLine"
android:minLines="5" >
</EditText>
<Button
android:id="@+id/add_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/add_record" />
</LinearLayout>
Zwei EditText-Komponenten, die die Eingaben für Land und Währung enthalten, sowie eine Schaltfläche, um die Werte zur Datenbank hinzuzufügen und sie in der ListView anzuzeigen, sind definiert. AddCountryActivity.java
package com.journaldev.sqlite;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class AddCountryActivity extends Activity implements OnClickListener {
private Button addTodoBtn;
private EditText subjectEditText;
private EditText descEditText;
private DBManager dbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Add Record");
setContentView(R.layout.activity_add_record);
subjectEditText = (EditText) findViewById(R.id.subject_edittext);
descEditText = (EditText) findViewById(R.id.description_edittext);
addTodoBtn = (Button) findViewById(R.id.add_record);
dbManager = new DBManager(this);
dbManager.open();
addTodoBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add_record:
final String name = subjectEditText.getText().toString();
final String desc = descEditText.getText().toString();
dbManager.insert(name, desc);
Intent main = new Intent(AddCountryActivity.this, CountryListActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(main);
break;
}
}
}
Die hier durchgeführte CRUD-Operation besteht darin, einen neuen Datensatz zur Datenbank hinzuzufügen. Das XML-Layout und der Code der Datei ModifyCountryActivity.java sind unten definiert: activity_modify_record.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" >
<EditText
android:id="@+id/subject_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:ems="10"
android:hint="@string/enter_title" />
<EditText
android:id="@+id/description_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/enter_desc"
android:inputType="textMultiLine"
android:minLines="5" >
</EditText>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/btn_update" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/btn_delete" />
</LinearLayout>
</LinearLayout>
Es ist ähnlich wie das vorherige Layout, außer dass Ändern- und Löschen-Schaltflächen hinzugefügt wurden. ModifyCountryActivity.java
package com.journaldev.sqlite;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class ModifyCountryActivity extends Activity implements OnClickListener {
private EditText titleText;
private Button updateBtn, deleteBtn;
private EditText descText;
private long _id;
private DBManager dbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Modify Record");
setContentView(R.layout.activity_modify_record);
dbManager = new DBManager(this);
dbManager.open();
titleText = (EditText) findViewById(R.id.subject_edittext);
descText = (EditText) findViewById(R.id.description_edittext);
updateBtn = (Button) findViewById(R.id.btn_update);
deleteBtn = (Button) findViewById(R.id.btn_delete);
Intent intent = getIntent();
String id = intent.getStringExtra("id");
String name = intent.getStringExtra("title");
String desc = intent.getStringExtra("desc");
_id = Long.parseLong(id);
titleText.setText(name);
descText.setText(desc);
updateBtn.setOnClickListener(this);
deleteBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_update:
String title = titleText.getText().toString();
String desc = descText.getText().toString();
dbManager.update(_id, title, desc);
this.returnHome();
break;
case R.id.btn_delete:
dbManager.delete(_id);
this.returnHome();
break;
}
}
public void returnHome() {
Intent home_intent = new Intent(getApplicationContext(), CountryListActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(home_intent);
}
}
Die hier durchgeführten CRUD-Operationen umfassen das Aktualisieren und Löschen eines Datensatzes. Die unten stehenden Bilder zeigen Screenshots des endgültigen Projektergebnisses. Das erste Bild ist die Ausgabe, die beim ersten Starten der Anwendung angezeigt wird. Das zweite Bild ist das Ergebnis, wenn die Menüoption in der ActionBar ausgewählt wird, um einen neuen Datensatz hinzuzufügen, wie unten gezeigt.
Das dritte Bild zeigt eine Ausgabe, wenn 3 Datensätze hinzugefügt sind:
Das vierte Bild zeigt die Ausgabe, wenn auf ein Listenelement geklickt wird, um einen Datensatz zu ändern oder zu löschen:
Das letzte Bild ist die Ausgabe, wenn ein Datensatz gelöscht wird. In diesem Beispiel löschen wir den ersten Datensatz:
Öffnen der Android SQLite-Datenbankdatei
Wie wir bereits in diesem Tutorial besprochen haben, wird die Datenbankdatei im internen Speicher gespeichert, der vom Android-Gerätemonitor aus zugänglich ist, wie auf dem Bild unten sichtbar. Um diese Datenbank anzuzeigen, müssen wir diese Datei vom Gerät auf unseren Desktop ziehen. Dies geschieht, indem Sie die Menüoption oben rechts wie im Bild unten auswählen:
Um diese Datei zu öffnen, laden Sie den SQLiteBrowser von diesem Link herunter. Die folgenden Ausschnitte zeigen das Schema und die Tabellen im Browser.
Um die Tabelle anzuzeigen, gehen Sie zum Tab „Daten durchsuchen“ oben. Das folgende Bild wird angezeigt:
Damit endet das Android SQLite Tutorial. Das endgültige Android SQLite Projekt kann über den unten stehenden Link heruntergeladen werden.
Source:
https://www.digitalocean.com/community/tutorials/android-sqlite-database-example-tutorial