Android 如何使用SQLite保存數據
簡介
對于重復數據或結構化數據(例如聯系信息),將數據保存到數據庫是理想選擇。android.database.sqlite 軟件包中提供了在 Android 上使用數據庫所需的 API。本篇文章介紹在 Android 上使用 SQLite 數據庫。
定義架構和協定
SQL 數據庫的主要原則之一是架構,即數據庫組織方式的正式聲明。架構反映在你用于創(chuàng)建數據庫的 SQL 語句中。您可能會發(fā)現創(chuàng)建伴隨類(稱為協定類)很有用,該類以系統(tǒng)化、自記錄的方式明確指定了架構的布局。
協定類是定義 URI、表和列名稱的常量的容器。通過協定類,您可以在同一軟件包的所有其他類中使用相同的常量。這樣一來,您就可以在一個位置更改列名稱并將其傳播到整個代碼中。
組織協定類的一種良好方法是將對整個數據庫而言具有全局性的定義放入類的根級別。然后,為每個表創(chuàng)建一個內部類。每個內部類都枚舉相應表的列。
注意:通過實現
BaseColumns接口,您的內部類可以繼承名為_ID的主鍵字段。
例如,以下協定定義了表示 RSS Feed 的單個表的表名稱和列名稱:
public final class FeedReaderContract {
// To prevent someone from accidentally instantiating the contract class,
// make the constructor private.
private FeedReaderContract() {}
/* Inner class that defines the table contents */
public static class FeedEntry implements BaseColumns {
// 表名
public static final String TABLE_NAME = "entry";
// 列名
public static final String COLUMN_NAME_TITLE = "title";
// 列名
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
}
}使用 SQL 創(chuàng)建數據庫
定義了數據庫的結構后,應實現用于創(chuàng)建和維護數據庫和表的方法。以下是用于創(chuàng)建和刪除表的一些語句:
// 創(chuàng)建數據庫表
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
FeedEntry._ID + " INTEGER PRIMARY KEY," +
FeedEntry.COLUMN_NAME_TITLE + " TEXT," +
FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)";
// 刪除數據庫表
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;就像您在設備的內部存儲空間中保存文件一樣,Android 會將您的數據庫存儲在您應用的私有文件夾中。您的數據很安全,因為在默認情況下,其他應用或用戶無法訪問此區(qū)域。
SQLiteOpenHelper 類包含一組用于管理數據庫的實用 API。當您使用此類獲取對數據庫的引用時,系統(tǒng)僅在需要時才執(zhí)行可能需要長時間運行的數據庫創(chuàng)建和更新操作,而不是在應用啟動期間執(zhí)行。您僅需調用 getWritableDatabase() 或 getReadableDatabase() 即可。
注意:由于這些操作可能會長時間運行,因此請務必在后臺線程中調用
getWritableDatabase()或getReadableDatabase()。
如需使用 SQLiteOpenHelper,請創(chuàng)建一個用于替換 onCreate() 和 onUpgrade() 回調方法的子類。您可能還需要實現 onDowngrade() 或 onOpen() 方法,但這些方法并非必需。
例如,下面展示了使用上述一些命令的 SQLiteOpenHelper 實現:
public class FeedReaderDbHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "FeedReader.db";
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
FeedEntry._ID + " INTEGER PRIMARY KEY," +
FeedEntry.COLUMN_NAME_TITLE + " TEXT," +
FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)";
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
public FeedReaderDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
// 創(chuàng)建數據庫表
db.execSQL(SQL_CREATE_ENTRIES);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// This database is only a cache for online data, so its upgrade policy is
// to simply to discard the data and start over
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}如需訪問您的數據庫,請實例化 SQLiteOpenHelper 的子類:
FeedReaderDbHelper dbHelper = new FeedReaderDbHelper(getContext());
將信息添加到數據庫
通過將 ContentValues 對象傳遞給 insert() 方法,將數據插入到數據庫中:
// Gets the data repository in write mode SQLiteDatabase db = dbHelper.getWritableDatabase(); // Create a new map of values, where column names are the keys ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_TITLE, title); values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle); // Insert the new row, returning the primary key value of the new row long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
insert()函數介紹
public long insert (String table,
String nullColumnHack,
ContentValues values)| Parameters | Details |
|---|---|
| table | String: 要插入行的表名,該值不能為空 |
| nullColumnHack | String: 可選;可為null。SQL 不允許在未命名至少一個列名的情況下插入完全為空的記錄。如果提供的值為空,則不知道列名,無法插入空行。如果不設置為空,nullColumnHack 參數會提供可空的列名,以便在值為空的情況下明確插入 NULL。 |
| values | ContentValues: 該映射包含該行的初始列值。鍵應該是列名,值應該是列值。該值可以為空。 |
| Returns | Details |
|---|---|
| long | 新插入行的行 ID,如果發(fā)生錯誤則為 -1 |
返回新創(chuàng)建行的 ID;如果在插入數據時出錯,會返回 -1。如果您的數據與數據庫中已有的數據之間存在沖突,就會出現這種情況。
從數據庫中讀取信息
如需從數據庫中讀取信息,請使用 query() 方法,向其傳遞您的選擇條件和所需的列。該方法合并了 insert() 和 update() 元素,不過列表定義了要提取的數據(“預測值”),而不是要插入的數據。查詢結果會包含在 Cursor 對象中返回給您。
SQLiteDatabase db = dbHelper.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
BaseColumns._ID,
FeedEntry.COLUMN_NAME_TITLE,
FeedEntry.COLUMN_NAME_SUBTITLE
};
// Filter results WHERE "title" = 'My Title'
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };
// How you want the results sorted in the resulting Cursor
String sortOrder =
FeedEntry.COLUMN_NAME_SUBTITLE + " DESC";
Cursor cursor = db.query(
FeedEntry.TABLE_NAME, // The table to query
projection, // The array of columns to return (pass null to get all)
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);delete()函數介紹
public Cursor query (String table, // 要查詢的表名,不能為空
String[] columns, // 要返回的列的列表。傳遞 null 將返回所有列
String selection, // 聲明要返回哪些行的過濾器,傳遞 null 將返回給定表的所有行
String[] selectionArgs, // 可以在選擇中包含 ?,它將被選擇參數中的值替換,按照它們在選擇中出現的順序
String groupBy, // 分組過濾器,傳遞 null 將導致行不被分組
String having, // 如果使用行分組,則過濾器聲明游標中包含哪些行組,傳遞 null 將導致包含所有行組
String orderBy) // 對行進行排序,傳遞 null 將使用默認排序順序,該順序可能是無序的第三個參數和第四個參數(selection 和 selectionArgs)會合并起來創(chuàng)建一個 WHERE 子句。由于這兩個參數是與選擇查詢分開提供的,因此它們在合并之前會進行轉義。這樣一來,您的選擇語句就不受 SQL 注入的影響。
如需查看光標中的某一行,請使用 Cursor move 方法之一,您必須始終在開始讀取值之前調用該方法。由于光標從位置 -1 開始,因此調用 moveToNext() 會將“讀取位置”置于結果的第一個條目上,并返回光標是否已經過結果集中的最后一個條目。對于每一行,您都可以通過調用 Cursor get 方法之一(例如 getString() 或 getLong())讀取列的值。對于每個 get 方法,您必須傳遞所需列的索引位置,您可以通過調用 getColumnIndex() 或 getColumnIndexOrThrow() 獲取該位置。遍歷結果之后,請對光標調用 close() 以釋放其資源。例如,以下代碼展示了如何獲取存儲在光標中的所有項目 ID 并將其添加到列表中:
List itemIds = new ArrayList<>();
while(cursor.moveToNext()) {
long itemId = cursor.getLong(
cursor.getColumnIndexOrThrow(FeedEntry._ID));
itemIds.add(itemId);
}
cursor.close();從數據庫中刪除信息
如需從表中刪除行,您需要提供選擇條件,以標識 delete() 方法的目標行。該機制與 query() 方法的目標選擇參數的工作方式相同。它將選擇規(guī)范劃分為選擇子句和選擇參數。子句定義要查看的列,并允許您合并列測試。參數是要測試的值,這些值綁定到子句中。由于結果的處理方式與常規(guī) SQL 語句的處理方式不同,因此不受 SQL 注入的影響。
// Define 'where' part of query.
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = { "MyTitle" };
// Issue SQL statement.
int deletedRows = db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);delete() 方法的返回值表示從數據庫中刪除的行數。
delete()函數介紹
// return: 如果傳入 whereClause,則影響的行數,否則為 0。要刪除所有行并獲取計數,請傳遞“1”作為 whereClause。
public int delete (String table, // 要操作的表名,不能為空
String whereClause, // 刪除時應用的可選 WHERE 子句。傳遞 null 將刪除所有行。
String[] whereArgs) // 可以在 where 子句中包含 ?s,它將被 whereArgs 中的值替換。這些值將綁定為字符串。如果 whereClause 為 null 或不包含 ?s,則 whereArgs 可能為 null。更新數據庫
如果您需要修改數據庫值的子集,請使用 update() 方法。
SQLiteDatabase db = dbHelper.getWritableDatabase();
// New value for one column
String title = "MyNewTitle";
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
// Which row to update, based on the title
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyOldTitle" };
int count = db.update(
FeedReaderDbHelper.FeedEntry.TABLE_NAME,
values,
selection,
selectionArgs);update() 方法的返回值是數據庫中受影響的行數。
update()函數介紹
public int update (String table, // 要更新的表名,不能為null
ContentValues values, // 從列名到新列值的映射。 null 是一個有效值,將被轉換為 NULL。
String whereClause, // 更新時應用的可選 WHERE 子句。傳遞 null 將更新所有行。
String[] whereArgs) // 可以在 where 子句中包含 ?s,它將被 whereArgs 中的值替換。這些值將綁定為字符串。如果 whereClause 為 null 或不包含 ?s,則 whereArgs 可能為 null。保留數據庫連接
由于在數據庫關閉時,調用 getWritableDatabase() 和 getReadableDatabase() 的成本比較高,因此只要您有可能需要訪問數據庫,就應保持數據庫連接處于打開狀態(tài)。通常情況下,最好在發(fā)出調用的 Activity 的 onDestroy() 中關閉數據庫。
@Override
protected void onDestroy() {
dbHelper.close();
super.onDestroy();
}調試數據庫
Android SDK 提供一個 sqlite3 shell 工具,您可以使用該工具瀏覽表內容、運行 SQL 命令以及在 SQLite 數據庫中執(zhí)行其他實用操作。
sqlite3 可啟動用于檢查 SQLite 數據庫的 sqlite 命令行程序。它包含用于輸出表格內容的 .dump 以及用于輸出現有表格的 SQL CREATE 語句的 .schema 等命令。您也可以從命令行執(zhí)行 SQLite 命令,如下所示:
$ adb -s emulator-5554 shell $ sqlite3 /data/data/com.example.app/databases/rssitems.db SQLite version 3.3.12 Enter ".help" for instructions
注意:您必須擁有對文件系統(tǒng)的 root 權限(例如在模擬器上),才能訪問 SQLite 數據庫。
到此這篇關于Android 使用SQLite保存數據的文章就介紹到這了,更多相關Android SQLite保存數據內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android EditText輸入框實現下拉且保存最近5個歷史記錄思路詳解
今天給大家介紹Android EditText輸入框實現下拉且保存最近5個歷史記錄功能,android實現文本框下拉利用sharedpreferences來保存每次app啟動和關閉時已經填寫的數值,具體代碼跟隨小編一起看看吧2021-07-07
Android查看電池電量的方法(基于BroadcastReceiver)
這篇文章主要介紹了Android查看電池電量的方法,結合實例分析了Android使用BroadcastReceiver實現針對電池電量的查詢技巧,需要的朋友可以參考下2016-01-01

