Exemple de tutoriel sur la base de données Android SQLite

Bienvenue dans le tutoriel d’exemple Android SQLite. Android SQLite est le moyen le plus préféré de stocker des données pour les applications Android. Pour de nombreuses applications, SQLite est la colonne vertébrale des applications, qu’elle soit utilisée directement ou via un wrapper tiers. Ci-dessous se trouve l’application finale que nous créerons aujourd’hui en utilisant la base de données Android SQLite.

Android SQLite

Android SQLite est une base de données très légère livrée avec Android OS. Android SQLite combine une interface SQL propre avec une empreinte mémoire très réduite et une vitesse décente. Pour Android, SQLite est « intégré » dans l’exécution Android, de sorte que chaque application Android peut créer ses propres bases de données SQLite. L’API native d’Android SQLite n’est pas JDBC, car JDBC pourrait être trop lourd pour un smartphone limité en mémoire. Une fois qu’une base de données est créée avec succès, elle est située dans data/data//databases/ accessible depuis le Moniteur de périphériques Android. SQLite est une base de données relationnelle typique, contenant des tables (qui se composent de lignes et de colonnes), des index, etc. Nous pouvons créer nos propres tables pour contenir les données en conséquence. Cette structure est appelée un schéma.

Android SQLite SQLiteOpenHelper

Android dispose de fonctionnalités permettant de gérer les changements de schéma de base de données, principalement en utilisant la classe SQLiteOpenHelper. SQLiteOpenHelper est conçu pour résoudre deux problèmes très courants.

  1. Lorsque l’application est lancée pour la première fois – À ce stade, nous n’avons pas encore de base de données. Nous devrons donc créer les tables, les index, les données de démarrage, etc.
  2. Lorsque l’application est mise à jour vers un schéma plus récent – Notre base de données sera toujours sur l’ancien schéma de l’édition précédente de l’application. Nous aurons la possibilité de modifier le schéma de la base de données pour répondre aux besoins du reste de l’application.

SQLiteOpenHelper encapsule cette logique pour créer et mettre à jour une base de données selon nos spécifications. Pour cela, nous devrons créer une sous-classe personnalisée de SQLiteOpenHelper implémentant au moins les trois méthodes suivantes.

  1. Constructeur : Celui-ci prend le contexte (par exemple, une activité), le nom de la base de données, une fabrique de curseurs facultative (nous en discuterons plus tard), et un entier représentant la version du schéma de la base de données que vous utilisez (commençant généralement par 1 et incrémentant par la suite).

    public DatabaseHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
        }
    
  2. onCreate(SQLiteDatabase db) : Il est appelé lorsqu’il n’y a pas de base de données et que l’application en a besoin. Il nous passe un objet SQLiteDatabase, pointant vers une base de données nouvellement créée, que nous pouvons peupler avec des tables et des données initiales.

  3. onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) : Il est appelé lorsque la version du schéma dont nous avons besoin ne correspond pas à la version du schéma de la base de données. Il nous passe un objet SQLiteDatabase et les anciennes et nouvelles numéros de version. Ainsi, nous pouvons trouver la meilleure façon de convertir la base de données du ancien schéma au nouveau.

Nous définissons une classe DBManager pour effectuer toutes les opérations CRUD (Créer, Lire, Mettre à jour et Supprimer) de la base de données.

Ouverture et Fermeture de la Connexion à la Base de Données Android SQLite

Avant d’effectuer des opérations de base de données telles que l’insertion, la mise à jour, la suppression d’enregistrements dans une table, ouvrez d’abord la connexion à la base de données en appelant la méthode getWritableDatabase() comme indiqué ci-dessous:

public DBManager open() throws SQLException {
        dbHelper = new DatabaseHelper(context);
        database = dbHelper.getWritableDatabase();
        return this;
    }

Le dbHelper est une instance de la sous-classe de SQLiteOpenHelper. Pour fermer une connexion à la base de données, la méthode suivante est invoquée.

 public void close() {
        dbHelper.close();
    }

Insertion d’un Nouvel Enregistrement dans la Table de la Base de Données Android SQLite

Le code ci-dessous montre comment insérer un nouvel enregistrement dans la base de données SQLite Android.

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);
    }

ContentValues crée un ensemble de valeurs vides en utilisant la taille initiale donnée. Nous discuterons des autres valeurs d’instance lorsque nous passerons à la partie codage.

Mise à Jour d’un Enregistrement dans la Table de la Base de Données Android SQLite

Le snippet suivant montre comment mettre à jour un enregistrement unique.

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 – Suppression d’un enregistrement

Il suffit de passer l’ID de l’enregistrement à supprimer comme indiqué ci-dessous.

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:

  • Cela nous permet de tester si la requête a renvoyé un ensemble vide (en testant la valeur de retour)
  • Il déplace le curseur sur le premier résultat (lorsque l’ensemble n’est pas vide)

Le code suivant est utilisé pour récupérer tous les enregistrements:

 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;
    }

Une autre façon d’utiliser un Cursor est de l’encapsuler dans un CursorAdapter. Tout comme ArrayAdapter s’adapte aux tableaux, CursorAdapter s’adapte aux objets Cursor, rendant leurs données disponibles à un AdapterView comme un ListView. Passons à notre projet qui utilise SQLite pour stocker des données significatives.

Structure du projet exemple Android SQLite

Dans cette application, nous souhaitons créer des enregistrements qui stockent les noms de pays et leurs devises respectives sous forme de ListView. Nous couvrons toutes les fonctionnalités discutées ci-dessus.

Code du Projet Android SQLite

L’application se compose de 5 classes. Nous commençons par définir avec DatabaseHelper, qui est une sous-classe de SQLiteOpenHelper comme suit: 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 {

    // Nom de la Table
    public static final String TABLE_NAME = "COUNTRIES";

    // Colonnes de la Table
    public static final String _ID = "_id";
    public static final String SUBJECT = "subject";
    public static final String DESC = "description";

    // Informations sur la Base de Données
    static final String DB_NAME = "JOURNALDEV_COUNTRIES.DB";

    // Version de la base de données
    static final int DB_VERSION = 1;

    // Requête de création de table
    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);
    }
}

Comme discuté ci-dessus, nous avons remplacé les méthodes onCreate() et onUpgrade() en plus du constructeur. Nous avons attribué les noms à la base de données et à la table respectivement JOURNALDEV_COUNTRIES.DB et COUNTRIES. La colonne d’index est incrémentée automatiquement à chaque nouvelle ligne insérée. Les noms de colonnes pour le pays et la devise sont « subject » et « description ». Les classes DBManager sont où DatabaseHelper est initialisé et les opérations CRUD sont définies. Voici le code pour cette classe: 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);
    }

}

La classe CountryListActivity.java est l’activité lancée lorsque l’application démarre. Voici la mise en page définie pour elle : 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>

Un composant ListView est défini ici pour inclure les enregistrements stockés dans la base de données. Initialement, le ListView serait vide, c’est pourquoi un TextView est utilisé pour l’afficher. 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 Pour les éléments de la liste
        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);
    }

}

Dans cette activité, l’objet DBManager est invoqué pour effectuer les opérations CRUD. Un SimpleCursorAdapter est défini pour ajouter des éléments à la liste à partir des résultats de la requête renvoyés dans un objet Cursor. Lorsque vous cliquez sur un élément de la liste, une intention est réalisée pour ouvrir la classe ModifyCountryActivity. Le menu contient un élément pour ajouter un nouvel enregistrement depuis l’ActionBar. Ici encore, une intention est réalisée pour ouvrir la classe AddCountryActivity. Voici le code de 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>

La mise en page XML et le code du fichier AddCountryActivity.java sont définis ci-dessous : 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>

Deux composants EditText qui prennent les saisies pour le pays et la devise ainsi qu’un bouton pour ajouter les valeurs à la base de données et les afficher dans le ListView sont définis. 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;
        }
    }

}

L’opération CRUD effectuée ici consiste à ajouter un nouvel enregistrement à la base de données. La mise en page XML et le code du fichier ModifyCountryActivity.java sont définis ci-dessous : 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>

Il est similaire à la mise en page précédente, sauf que des boutons de modification et de suppression sont ajoutés. 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);
    }
}

Les opérations CRUD effectuées ici consistent à mettre à jour et supprimer un enregistrement. Les images ci-dessous sont des captures d’écran du résultat final de notre projet. La première image est le résultat vu lorsque l’application est lancée pour la première fois. La deuxième image est le résultat de la sélection de l’option de menu dans l’ActionBar pour ajouter un nouvel enregistrement, comme indiqué ci-dessous. La troisième image montre un résultat lorsqu’il y a 3 enregistrements ajoutés : La quatrième image montre le résultat lorsqu’un élément de liste est cliqué pour modifier ou supprimer un enregistrement : La dernière image est le résultat lorsqu’un enregistrement est supprimé. Dans cet exemple, nous supprimons le premier enregistrement :

Ouverture du fichier de base de données SQLite Android

Comme nous l’avons discuté précédemment dans ce tutoriel, le fichier de base de données est stocké dans le stockage interne qui est accessible depuis le Moniteur de périphérique Android comme visible dans l’image ci-dessous. Pour visualiser cette base de données, nous devons extraire ce fichier du périphérique vers notre bureau. Cela se fait en cliquant sur l’option de menu en haut à droite comme vu dans l’image ci-dessous : Pour ouvrir ce fichier, téléchargez SQLiteBrowser depuis ce lien. Les extraits ci-dessous montrent le schéma et les tables dans le navigateur. Pour afficher la table, accédez à l’onglet Parcourir les données en haut. L’image suivante est visible : Cela met fin au tutoriel Android SQLite. Le Projet Android SQLite final est téléchargeable depuis le lien ci-dessous.

Télécharger le Projet d’Exemple Android SQLite

Source:
https://www.digitalocean.com/community/tutorials/android-sqlite-database-example-tutorial