編輯:關於Android編程
SQLite 是一款輕量級的關系型數據庫
Android為了讓我們能夠更加方便地管理數據庫,專門提供了一個SQLiteOpenHelper幫助類,借助這個類就可以非常簡單地對數據庫進行創建和升級。
SQLiteOpenHelper是一個抽象類。
SQLiteOpenHelper中有兩個抽象方法,分別是onCreate()和onUpgrade()。
SQLiteOpenHelper中還有兩個非常重要的實例方法,getReadableDatabase()和getWritableDatabase()。
數據庫文件存放在 : /data/data/
SQLite不像其他的數據庫擁有眾多繁雜的數據類型,它的數據類型很簡單,integer表示整型,real表示浮點型,text表示文本類型,blob表示二進制類型。
SQLiteOpenHelper中有兩個構造方法可供重寫。
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { this(context, name, factory, version, null); }
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version); mContext = context; mName = name; mFactory = factory; mNewVersion = version; mErrorHandler = errorHandler; }
創建數據庫
舉個栗子:
創建一個BookStore.db的數據庫。然後在這個數據庫中新建一張Book表,表中有id(主鍵)、作者、價格、頁數和書名等列。
建表語句
create table Book ( id integer primary key autoincrement, author text, price real, pages integer, name text)
升級數據庫
再添加一張Category表用於記錄書籍的分類。
Category表中有id(主鍵)、分類名和分類代碼
create table Category ( id integer primary key autoincrement, category_name text, category_code integer)
@Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT). show(); }
因為此時BookStore.db數據庫已經存在了,之後不管我們怎樣點擊Create database按鈕,MyDatabaseHelper中的onCreate()方法都不會再次執行,因此新添加的表也就無法得到創建了。
需要更改update方法
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists Book"); db.execSQL("drop table if exists Category"); onCreate(db); }
更改數據庫版本號後,運行項目。即可更新數據庫。創建了Category表。
但是這種方法是相當粗暴。直接刪表。在正常的產品項目中是不可能這麼干的。
正確的更新數據庫方法是:
@Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { case 1: db.execSQL(CREATE_CATEGORY); default: } }在onCreate()方法裡我們新增了一條建表語句,然後又在onUpgrade()方法中添加了一個switch判斷,如果用戶當前數據庫的版本號是1,就只會創建一張Category表。這樣當用戶是直接安裝的第二版的程序時,就會將兩張表一起創建。而當用戶是使用第二版的程序覆蓋安裝第一版的程序時,就會進入到升級數據庫的操作中,此時由於Book表已經存在了,因此只需要創建一張Category表即可。
ADB 查詢數據庫
如果使用FileExplorer ,最多只能看到databases目錄下有一個BookStore.db 文件。
要查詢數據庫數據,需要 使用 adb shell 。
adb.exe 存放在sdk的platform-tools目錄下,如果想要在命令行中使用這個工具,就需要先把它的路徑配置到環境變量裡。
如果你使用的是Windows系統,可以右擊我的電腦→屬性→高級→環境變量,然後在系統變量裡找到Path並點擊編輯,將platform-tools目錄配置進去。如果要使用真機調試程序,真機需要root權限。
配置好環境變量後,輸入 adb shell 。如果出現如下格式。說明adb 指令權限不夠。再輸入 su 指令即可。
C:\Users\Tan>adb shell
shell@cancro:/ $
輸入su 後,顯示:
C:\Users\Tan>adb shell
shell@cancro:/ $ su
root@cancro:/ #
參考: adb shell 訪問真機手機數據庫文件
進入數據後,用sqlite3 指令增刪改查數據時,會提示sqlite3 不是內部指令。這是因為手機中沒有sqlite3 文件。
解決辦法:參考如何設置Android手機的sqlite3命令環境
如果條件允許可以使用模擬器。模擬器是支持sqlite3指令集的。
也可以使用【RootExplorerRE文件管理器.apk】 ,安裝到手機上直接查看手機data/data/目錄下的文件。查看數據庫。但是需要手機root權限。
下載地址:下載鏈接
也可以將 數據庫文件導出,然後利用第三方插件查看。參考:Android開發工具---SQLiteManager插件
輸入 adb shell
然後使用cd命令進行到 /data/data/com.example.databasetest/databases/目錄下 (注意cd 後面有空格)
使用ls命令查看到該目錄裡的文件
接下來我們就要借助sqlite命令來打開數據庫了,只需要鍵入sqlite3,後面加上數據庫名即可。 sqlite3 BookStore.db
進入數據庫後,
輸入.table 查看數據庫中的表
輸入.schema 查看建表語句
鍵入.exit或.quit命令可以退出數據庫的編輯,再鍵入exit命令就可以退出設備控制台了。
添加數據
我們可以對數據進行的操作也就無非四種,即CRUD。其中C代表添加(Create),R代表查詢(Retrieve),U代表更新(Update),D代表刪除(Delete)。每一種操作又各自對應了一種SQL命令,添加數據時使用insert,查詢數據時使用select,更新數據時使用update,刪除數據時使用delete。
方法一:
insert()方法
接收三個參數,第一個參數是表名,我們希望向哪張表裡添加數據,這裡就傳入該表的名字。
第二個參數用於在未指定添加數據的情況下給某些可為空的列自動賦值NULL,一般我們用不到這個功能,直接傳入null即可。
第三個參數是一個ContentValues對象,它提供了一系列的put()方法重載,用於向ContentValues中添加數據,只需要將表中的每個列名以及相應的待添加數據傳入即可。
Button addData = (Button) findViewById(R.id.add_data); addData.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); // 開始組裝第一條數據 values.put("name", "The Da Vinci Code"); values.put("author", "Dan Brown"); values.put("pages", 454); values.put("price", 16.96); db.insert("Book", null, values); // 插入第一條數據 values.clear(); // 開始組裝第二條數據 values.put("name", "The Lost Symbol"); values.put("author", "Dan Brown"); values.put("pages", 510); values.put("price", 19.95); db.insert("Book", null, values); // 插入第二條數據 } });
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)", new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" }); db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)", new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });
db.execSQL 方法:
用adb 進入BookStores.db 數據庫。輸入查詢語句 select * from Book ,即可查看表中的數據。
方法三:在adb 指令中,用sql 語句增加數據。
adb shell
cd /data/data/com.example.databasetest/databases/ //進入數據庫目錄
ls //查看目錄下文件
sqlite3 BookStore.db // 利用sqlite3 指令進入數據庫
.table //查看數據庫中的表
select * from Book; //查詢Book表中的數據
insert into Book ( name , author , pages , price) values ('diyihangdaima' , 'guolin', '550' ,'70.5');
//向Book表中插入一條數據
// 注意 ,用 insert into 指令 ,key 值和values 值 不能用 new String[] {"diyihsangdaima "……} 這種格式。並且,values中的值用單引號。
select * from Book; //查詢Book表中的數據
更新數據
方法一:
update() ; 方法
方法接收四個參數,
第一個參數和insert()方法一樣,也是表名,在這裡指定去更新哪張表裡的數據。
第二個參數是ContentValues對象,要把更新數據在這裡組裝進去。
第三、第四個參數用於去約束更新某一行或某幾行中的數據,不指定的話默認就是更新所有行。
Button updateData = (Button) findViewById(R.id.update_data); updateData.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("price", 10.99); db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" }); } });
方法二:
db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99", "The Da Vinci Code" });
方法三:
在cmd中用sqlite3 指令更新數據;
sqlite> update Book set price = '9.99' where id = 1; //更新ID=1 的數據 sqlite> update Book set price = '50' where author = 'guolin'; // 更新author 為guolin的數據
刪除數據
方法一:
delete()方法
方法接收三個參數,
第一個參數仍然是表名
第二、第三個參數又是用於去約束刪除某一行或某幾行的數據,不指定的話默認就是刪除所有行
Button deleteButton = (Button) findViewById(R.id.delete_data); deleteButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dbHelper.getWritableDatabase(); db.delete("Book", "pages > ?", new String[] { "500" }); } });
db.execSQL("delete from Book where pages > ?", new String[] { "500" });
方法三:
sqlite> delete from Book where id = 1; sqlite> delete from Book where author = 'guolin';
SQL的全稱是Structured Query Language,翻譯成中文就是結構化查詢語言
方法一:
query();
query()方法用於對數據進行查詢。這個方法的參數非常復雜,最短的一個方法重載也需要傳入七個參數。那我們就先來看一下這七個參數各自的含義吧,
第一個參數不用說,當然還是表名,表示我們希望從哪張表中查詢數據。
第二個參數用於指定去查詢哪幾列,如果不指定則默認查詢所有列。
第三、第四個參數用於去約束查詢某一行或某幾行的數據,不指定則默認是查詢所有行的數據。
第五個參數用於指定需要去group by的列,不指定則表示不對查詢結果進行group by操作。
第六個參數用於對group by之後的數據進行進一步的過濾,不指定則表示不進行過濾。
第七個參數用於指定查詢結果的排序方式,不指定則表示使用默認的排序方式。
query()方法參數
對應SQL部分
描述
table
from table_name
指定查詢的表名
columns
select column1, column2
指定查詢的列名
selection
where column = value
指定where的約束條件
selectionArgs
-
為where中的占位符提供具體的值
groupBy
group by column
指定需要group by的列
having
having column = value
對group by後的結果進一步約束
orderBy
order by column1, column2
指定查詢結果的排序方式
Button queryButton = (Button) findViewById(R.id.query_data); queryButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dbHelper.getWritableDatabase(); // 查詢Book表中所有的數據 Cursor cursor = db.query("Book", null, null, null, null, null, null); if (cursor.moveToFirst()) { do { // 遍歷Cursor對象,取出數據並打印 String name = cursor.getString(cursor. getColumnIndex("name")); String author = cursor.getString(cursor. getColumnIndex("author")); int pages = cursor.getInt(cursor.getColumnIndex ("pages")); double price = cursor.getDouble(cursor. getColumnIndex("price")); Log.d("MainActivity", "book name is " + name); Log.d("MainActivity", "book author is " + author); Log.d("MainActivity", "book pages is " + pages); Log.d("MainActivity", "book price is " + price); } while (cursor.moveToNext()); } cursor.close(); // 不關閉會導致內存洩漏 } });
方法二:
db.rawQuery("select * from Book", null);
方法三:
sqlite
select * from Book;
sqlite> select price from Book; 19.95 16.96 19.95
Button replaceData = (Button) findViewById(R.id.replace_data); replaceData.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); // 開啟事務 try { db.delete("Book", null, null); if (true) { // 在這裡手動拋出一個異常,讓事務失敗 throw new NullPointerException(); } ContentValues values = new ContentValues(); values.put("name", "Game of Thrones"); values.put("author", "George Martin"); values.put("pages", 720); values.put("price", 20.85); db.insert("Book", null, values); db.setTransactionSuccessful(); // 事務已經執行成功 } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); // 結束事務 } } });
數據庫升級最佳寫法
給Book表和Category表之間建立關聯,需要在Book表中添加一個category_id的字段。
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table Book (" + "id integer primary key autoincrement, " + "author text, " + "price real, " + "pages integer, " + "name text, " + "category_id integer)"; public static final String CREATE_CATEGORY = "create table Category (" + "id integer primary key autoincrement, " + "category_name text, " + "category_code integer)"; public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { case 1: db.execSQL(CREATE_CATEGORY); case 2: db.execSQL("alter table Book add column category_id integer"); default: } } }
在onUpgrade()方法裡,我們添加了一個新的case,如果當前數據庫的版本號是2,就會執行alter命令來為Book表新增一個category_id列。
switch中每一個case的最後都是沒有使用break的!
Android Camera探究之路——起步Camera在手機中有著舉足輕重的地位,不管是二維碼還是照片、識別,都離不開攝像頭,本文將對Andro
首先呈上效果圖當今APP,哪個沒有點滑動刷新功能,簡直就太落伍了。正因為需求多,因此自然而然開源的也就多。但是若想引用開源庫,則很麻煩,比如PullToRefreshVi
本文實例為大家分享了Android二級橫向菜單的實現過程.效果如上圖: 這種橫向的二級菜單在很多的app都有所應用.效果看起來還是非常的美觀的.也
異步任務 AsyncTask使用 android中實現異步機制主要有Thread加Handler和AsyncTask,今天主要記錄一下A