欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 如何使用SQLite保存數(shù)據(jù)

 更新時間:2024年03月30日 11:15:07   作者:tracydragonlxy  
對于重復(fù)數(shù)據(jù)或結(jié)構(gòu)化數(shù)據(jù)(例如聯(lián)系信息),將數(shù)據(jù)保存到數(shù)據(jù)庫是理想選擇,SQL 數(shù)據(jù)庫的主要原則之一是架構(gòu),即數(shù)據(jù)庫組織方式的正式聲明,本篇文章介紹在 Android 上使用 SQLite 數(shù)據(jù)庫,感興趣的朋友一起看看吧

簡介

對于重復(fù)數(shù)據(jù)或結(jié)構(gòu)化數(shù)據(jù)(例如聯(lián)系信息),將數(shù)據(jù)保存到數(shù)據(jù)庫是理想選擇。android.database.sqlite 軟件包中提供了在 Android 上使用數(shù)據(jù)庫所需的 API。本篇文章介紹在 Android 上使用 SQLite 數(shù)據(jù)庫。

定義架構(gòu)和協(xié)定

SQL 數(shù)據(jù)庫的主要原則之一是架構(gòu),即數(shù)據(jù)庫組織方式的正式聲明。架構(gòu)反映在你用于創(chuàng)建數(shù)據(jù)庫的 SQL 語句中。您可能會發(fā)現(xiàn)創(chuàng)建伴隨類(稱為協(xié)定類)很有用,該類以系統(tǒng)化、自記錄的方式明確指定了架構(gòu)的布局。

協(xié)定類是定義 URI、表和列名稱的常量的容器。通過協(xié)定類,您可以在同一軟件包的所有其他類中使用相同的常量。這樣一來,您就可以在一個位置更改列名稱并將其傳播到整個代碼中。

組織協(xié)定類的一種良好方法是將對整個數(shù)據(jù)庫而言具有全局性的定義放入類的根級別。然后,為每個表創(chuàng)建一個內(nèi)部類。每個內(nèi)部類都枚舉相應(yīng)表的列。

注意:通過實現(xiàn) BaseColumns 接口,您的內(nèi)部類可以繼承名為 _ID 的主鍵字段。

例如,以下協(xié)定定義了表示 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)建數(shù)據(jù)庫

定義了數(shù)據(jù)庫的結(jié)構(gòu)后,應(yīng)實現(xiàn)用于創(chuàng)建和維護數(shù)據(jù)庫和表的方法。以下是用于創(chuàng)建和刪除表的一些語句:

// 創(chuàng)建數(shù)據(jù)庫表
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)";
// 刪除數(shù)據(jù)庫表
private static final String SQL_DELETE_ENTRIES =
    "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

就像您在設(shè)備的內(nèi)部存儲空間中保存文件一樣,Android 會將您的數(shù)據(jù)庫存儲在您應(yīng)用的私有文件夾中。您的數(shù)據(jù)很安全,因為在默認情況下,其他應(yīng)用或用戶無法訪問此區(qū)域。

SQLiteOpenHelper 類包含一組用于管理數(shù)據(jù)庫的實用 API。當您使用此類獲取對數(shù)據(jù)庫的引用時,系統(tǒng)僅在需要時才執(zhí)行可能需要長時間運行的數(shù)據(jù)庫創(chuàng)建和更新操作,而不是在應(yīng)用啟動期間執(zhí)行。您僅需調(diào)用 getWritableDatabase()getReadableDatabase() 即可。

注意:由于這些操作可能會長時間運行,因此請務(wù)必在后臺線程中調(diào)用 getWritableDatabase()getReadableDatabase()。

如需使用 SQLiteOpenHelper,請創(chuàng)建一個用于替換 onCreate()onUpgrade() 回調(diào)方法的子類。您可能還需要實現(xiàn) onDowngrade()onOpen() 方法,但這些方法并非必需。

例如,下面展示了使用上述一些命令的 SQLiteOpenHelper 實現(xiàn):

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)建數(shù)據(jù)庫表
        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);
    }
}

如需訪問您的數(shù)據(jù)庫,請實例化 SQLiteOpenHelper 的子類:

FeedReaderDbHelper dbHelper = new FeedReaderDbHelper(getContext());

將信息添加到數(shù)據(jù)庫

通過將 ContentValues 對象傳遞給 insert() 方法,將數(shù)據(jù)插入到數(shù)據(jù)庫中:

// 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()函數(shù)介紹

public long insert (String table, 
                String nullColumnHack, 
                ContentValues values)
ParametersDetails
tableString: 要插入行的表名,該值不能為空
nullColumnHackString: 可選;可為null。SQL 不允許在未命名至少一個列名的情況下插入完全為空的記錄。如果提供的值為空,則不知道列名,無法插入空行。如果不設(shè)置為空,nullColumnHack 參數(shù)會提供可空的列名,以便在值為空的情況下明確插入 NULL。
valuesContentValues: 該映射包含該行的初始列值。鍵應(yīng)該是列名,值應(yīng)該是列值。該值可以為空。
ReturnsDetails
long新插入行的行 ID,如果發(fā)生錯誤則為 -1

返回新創(chuàng)建行的 ID;如果在插入數(shù)據(jù)時出錯,會返回 -1。如果您的數(shù)據(jù)與數(shù)據(jù)庫中已有的數(shù)據(jù)之間存在沖突,就會出現(xiàn)這種情況。

從數(shù)據(jù)庫中讀取信息

如需從數(shù)據(jù)庫中讀取信息,請使用 query() 方法,向其傳遞您的選擇條件和所需的列。該方法合并了 insert()update() 元素,不過列表定義了要提取的數(shù)據(jù)(“預(yù)測值”),而不是要插入的數(shù)據(jù)。查詢結(jié)果會包含在 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()函數(shù)介紹

public Cursor query (String table, 	// 要查詢的表名,不能為空
                String[] columns, 	// 要返回的列的列表。傳遞 null 將返回所有列
                String selection, 	// 聲明要返回哪些行的過濾器,傳遞 null 將返回給定表的所有行
                String[] selectionArgs,  // 可以在選擇中包含 ?,它將被選擇參數(shù)中的值替換,按照它們在選擇中出現(xiàn)的順序
                String groupBy, 	// 分組過濾器,傳遞 null 將導(dǎo)致行不被分組
                String having, 		// 如果使用行分組,則過濾器聲明游標中包含哪些行組,傳遞 null 將導(dǎo)致包含所有行組
                String orderBy)		// 對行進行排序,傳遞 null 將使用默認排序順序,該順序可能是無序的

第三個參數(shù)和第四個參數(shù)(selectionselectionArgs)會合并起來創(chuàng)建一個 WHERE 子句。由于這兩個參數(shù)是與選擇查詢分開提供的,因此它們在合并之前會進行轉(zhuǎn)義。這樣一來,您的選擇語句就不受 SQL 注入的影響。

如需查看光標中的某一行,請使用 Cursor move 方法之一,您必須始終在開始讀取值之前調(diào)用該方法。由于光標從位置 -1 開始,因此調(diào)用 moveToNext() 會將“讀取位置”置于結(jié)果的第一個條目上,并返回光標是否已經(jīng)過結(jié)果集中的最后一個條目。對于每一行,您都可以通過調(diào)用 Cursor get 方法之一(例如 getString()getLong())讀取列的值。對于每個 get 方法,您必須傳遞所需列的索引位置,您可以通過調(diào)用 getColumnIndex()getColumnIndexOrThrow() 獲取該位置。遍歷結(jié)果之后,請對光標調(diào)用 close() 以釋放其資源。例如,以下代碼展示了如何獲取存儲在光標中的所有項目 ID 并將其添加到列表中:

List itemIds = new ArrayList<>();
while(cursor.moveToNext()) {
  long itemId = cursor.getLong(
      cursor.getColumnIndexOrThrow(FeedEntry._ID));
  itemIds.add(itemId);
}
cursor.close();

從數(shù)據(jù)庫中刪除信息

如需從表中刪除行,您需要提供選擇條件,以標識 delete() 方法的目標行。該機制與 query() 方法的目標選擇參數(shù)的工作方式相同。它將選擇規(guī)范劃分為選擇子句和選擇參數(shù)。子句定義要查看的列,并允許您合并列測試。參數(shù)是要測試的值,這些值綁定到子句中。由于結(jié)果的處理方式與常規(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() 方法的返回值表示從數(shù)據(jù)庫中刪除的行數(shù)。

delete()函數(shù)介紹

// return: 如果傳入 whereClause,則影響的行數(shù),否則為 0。要刪除所有行并獲取計數(shù),請傳遞“1”作為 whereClause。
public int delete (String table, 		// 要操作的表名,不能為空
                String whereClause, 	// 刪除時應(yīng)用的可選 WHERE 子句。傳遞 null 將刪除所有行。
                String[] whereArgs)		// 可以在 where 子句中包含 ?s,它將被 whereArgs 中的值替換。這些值將綁定為字符串。如果 whereClause 為 null 或不包含 ?s,則 whereArgs 可能為 null。

更新數(shù)據(jù)庫

如果您需要修改數(shù)據(jù)庫值的子集,請使用 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() 方法的返回值是數(shù)據(jù)庫中受影響的行數(shù)。

update()函數(shù)介紹

public int update (String table, 			// 要更新的表名,不能為null
                ContentValues values, 		// 從列名到新列值的映射。 null 是一個有效值,將被轉(zhuǎn)換為 NULL。
                String whereClause, 		// 更新時應(yīng)用的可選 WHERE 子句。傳遞 null 將更新所有行。
                String[] whereArgs)			// 可以在 where 子句中包含 ?s,它將被 whereArgs 中的值替換。這些值將綁定為字符串。如果 whereClause 為 null 或不包含 ?s,則 whereArgs 可能為 null。

保留數(shù)據(jù)庫連接

由于在數(shù)據(jù)庫關(guān)閉時,調(diào)用 getWritableDatabase()getReadableDatabase() 的成本比較高,因此只要您有可能需要訪問數(shù)據(jù)庫,就應(yīng)保持數(shù)據(jù)庫連接處于打開狀態(tài)。通常情況下,最好在發(fā)出調(diào)用的 Activity 的 onDestroy() 中關(guān)閉數(shù)據(jù)庫。

@Override
protected void onDestroy() {
    dbHelper.close();
    super.onDestroy();
}

調(diào)試數(shù)據(jù)庫

Android SDK 提供一個 sqlite3 shell 工具,您可以使用該工具瀏覽表內(nèi)容、運行 SQL 命令以及在 SQLite 數(shù)據(jù)庫中執(zhí)行其他實用操作。

sqlite3 可啟動用于檢查 SQLite 數(shù)據(jù)庫的 sqlite 命令行程序。它包含用于輸出表格內(nèi)容的 .dump 以及用于輸出現(xiàn)有表格的 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 權(quán)限(例如在模擬器上),才能訪問 SQLite 數(shù)據(jù)庫。

如需了解詳情,請參閱 sqlite3 命令行文檔。

到此這篇關(guān)于Android 使用SQLite保存數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Android SQLite保存數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論