前言
之前介紹過Android中保存數(shù)據(jù)的兩種方式:SharedPreferences和File,這篇介紹另一種存儲數(shù)據(jù)的方式——數(shù)據(jù)庫。
數(shù)據(jù)庫:簡單來說可視為電子化的文件柜——存儲電子文件的處所,用戶可以對文件中的數(shù)據(jù)運行新增撩银、截取、更新、刪除等操作荷愕。
想必大家對數(shù)據(jù)庫都不陌生,想當(dāng)年上數(shù)據(jù)庫課的時候棍矛,被那些命令整得不要不要的安疗。
扯遠(yuǎn)了...
進(jìn)入正題,在Android開發(fā)的過程中够委,保存數(shù)據(jù)是難免的荐类。如果數(shù)據(jù)量較小的時候可用SharedPreferences或File來保存,當(dāng)數(shù)據(jù)量較大且關(guān)系復(fù)雜的時候就要用到Android中的數(shù)據(jù)庫SQLite——輕量級數(shù)據(jù)庫系統(tǒng)茁帽。
用法
舉一個保存用戶信息的栗子:
創(chuàng)建一個數(shù)據(jù)庫mySQLite玉罐,在該數(shù)據(jù)庫中創(chuàng)建一個user表屈嗤,用來保存用戶信息,用戶屬性name(姓名:String類型)吊输、age(年齡:int類型)饶号。
創(chuàng)建一個用戶類(方便后面的操作)
/**
* 用戶
* Created by Gavin on 2016/5/30.
*/
public class User {
/**
* id
*/
private int id;
/**
* 用戶名
*/
private String name;
/**
* 年齡
*/
private int age;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
創(chuàng)建一個DatabaseHelper類
用來處理所有的數(shù)據(jù)庫操作。(這用到了SQL語句季蚂,不懂的看解釋)
/**
* Created by Gavin on 2016/5/30.
*/
public class DatabaseHelper extends SQLiteOpenHelper {
/**
* 數(shù)據(jù)庫版本,需要升級數(shù)據(jù)庫時只要加一即可
*/
private static final int DATABASE_VERSION = 1;
/**
* 數(shù)據(jù)庫名
*/
private static final String DATABASE_NAME = "mySQLite.db";
/**
* 構(gòu)造方法
* 每次創(chuàng)建DatabaseHelper對象時扭屁,若本應(yīng)用無該數(shù)據(jù)庫,則新建數(shù)據(jù)庫并調(diào)用onCreate方法然眼;
* 若該數(shù)據(jù)庫已創(chuàng)建則直接使用已存在的數(shù)據(jù)庫且跳過onCreate方法
* @param context 上下文
*/
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* 創(chuàng)建數(shù)據(jù)庫是時調(diào)用(只被調(diào)用一次)
* @param db 數(shù)據(jù)庫
*/
@Override
public void onCreate(SQLiteDatabase db) {
//創(chuàng)建user表,屬性:id(用戶id葵腹,主鍵)罪治、name(姓名)觉义、age(年齡)
db.execSQL("CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(10),age INTEGER)");
}
/**
* 跟新數(shù)據(jù)庫時調(diào)用
* @param db 數(shù)據(jù)庫
* @param oldVersion 舊版本號
* @param newVersion 新版本號
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//升級:往user表,添加性別屬性
//db.execSQL("ALTER TABLE user ADD COLUMN gender VARCHAR(2)");
}
}
數(shù)據(jù)庫mySQLite在構(gòu)造方法中創(chuàng)建浴井,其中super()的參數(shù)有4個:
context:上下文晒骇;
datebaseName:數(shù)據(jù)庫名,一般以.db結(jié)尾洪囤;
factory : 當(dāng)打開的數(shù)據(jù)庫執(zhí)行查詢語句的時候 會創(chuàng)建一個Cursor對象, 這時會調(diào)用Cursor工廠類 factory, 可以填寫null默認(rèn)值撕氧;
version:數(shù)據(jù)庫版本伦泥,需要升級數(shù)據(jù)庫時將版本號加一,將升級的內(nèi)容寫在onUpgrade中即可不脯。
- onCreate
當(dāng)數(shù)據(jù)庫第一次創(chuàng)建的時候,會執(zhí)行onCreate()方法牺丙。這里的onCreate方法中創(chuàng)建了一張user表复局,db.execSQL()方法執(zhí)行了里面SQL語句。
- onUpgrade
數(shù)據(jù)庫升級時會調(diào)用onUpgrade()方法峦剔,這里的onUpgrade()方法往user表中添加了性別(gender)屬性。
操作數(shù)據(jù)庫
操作數(shù)據(jù)庫事秀,增刪查改是免不了的野舶。下面的方法都是在DatabaseHelper 中添加平道。
- 增(Create)
/**
* 插入一條數(shù)據(jù)
* @param user 用戶對象
*/
public void insertAUser(User user) {
//如果要對數(shù)據(jù)進(jìn)行更改,就調(diào)用此方法得到用于操作數(shù)據(jù)庫的實例,
//該方法以讀和寫方式打開數(shù)據(jù)庫
SQLiteDatabase database = getWritableDatabase();
//向user表插入一條數(shù)據(jù)
database.execSQL(
"INSERT INTO user(name, age) VALUES(?,?)",
new Object[]{user.getName(), user.getAge()});
}
insertAUser()中使用了execSQL()執(zhí)行了插入數(shù)據(jù)的操作一屋。
這里用到的execSQL()有兩個參數(shù):
參數(shù)1:SQL指令冀墨,這里是一條插入命令涛贯,命令中的問號(?)為占位符
參數(shù)2:Object數(shù)組虫腋,數(shù)組中的內(nèi)容對應(yīng)參數(shù)1中的問號(稀余?)
- 刪(Delete)
/**
* 根據(jù)id刪除一條數(shù)據(jù)
* @param id 用戶id
*/
public void deleteAUser(Integer id) {
SQLiteDatabase database = getWritableDatabase();
//根據(jù)id刪除一條數(shù)據(jù)
database.execSQL("DELETE FROM user WHERE id=?",
new Object[]{id});
}
deleteAUser()根據(jù)用戶id睛琳,刪除了對應(yīng)的用戶信息。這里也是用了execSQL()執(zhí)行數(shù)據(jù)操作茁影。
- 查(Read)
/**
* 讀取一條數(shù)據(jù)
* @param id 用戶id
* @return 用戶對象
*/
public User readAUser(Integer id) {
//如果只對數(shù)據(jù)進(jìn)行讀取丧凤,建議使用此方法
SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.rawQuery(
"SELECT * FROM user WHERE id=?",
new String[]{id.toString()});
if (cursor.moveToFirst()) {
//讀取數(shù)據(jù),并返回
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndex("id")));
user.setName(cursor.getString(cursor.getColumnIndex("name")));
user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
cursor.close();
return user;
} else {
//未讀出數(shù)據(jù)浩螺,返回空數(shù)據(jù)
return null;
}
}
/**
* 獲取整個用戶列表
* @return
*/
public List<User> readAllUser() {
SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM user", new String[]{});
List<User> list = new ArrayList<User>();
//使用moveToNext()逐條讀取
while (cursor.moveToNext()) {
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndex("id")));
user.setName(cursor.getString(cursor.getColumnIndex("name")));
user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
list.add(user);
}
cursor.close();
return list;
}
readAUser()中使用rawQuery方法獲取到用戶信息要出,通過cursor.moveToFirst()來獲取cursor的第一條數(shù)據(jù),接著通過cursor.getInt()或颊、cursor.getString()來獲取對應(yīng)的數(shù)據(jù)传于。
這里使用了getReadableDatabase()而不是getWritableDatabase()
- Cursor
是每行的集合沼溜。詳情請參考Android 中關(guān)于 【Cursor】 類的介紹
- 改(Update)
/**
* 更新一條用戶數(shù)據(jù)
* @param user 用戶對象
*/
public void updateAUser(User user) {
SQLiteDatabase database = getWritableDatabase();
//根據(jù)id更新一條數(shù)據(jù)
database.execSQL(
"UPDATE user SET name=?, age=? WHERE id=?",
new Object[]{user.getName(), user.getAge(), user.getId()});
}
這也沒什么好說的~~
execSQL()中用到的都最基礎(chǔ)的是SQL指令,至于復(fù)雜的自己去查吧
使用
輔助類DatabaseHelper寫完了通熄,接下來就是使用了
- 插入一條數(shù)據(jù)
DatabaseHelper helper = new DatabaseHelper(this);
User user1 = new User();
user1.setName("lisa");
user1.setAge(20);
helper.insertAUser(user1);//插入一條數(shù)據(jù)
Log.i(TAG, helper.readAllUser().toString());//查看所有用戶
結(jié)果
- 根據(jù)id獲取一條數(shù)據(jù)唇辨,修改能耻,刪除。上面我們看到嗡贺,插入的那條數(shù)據(jù)id是1
DatabaseHelper helper = new DatabaseHelper(this);
User user1 = helper.readAUser(1); //查找id為1的用戶
Log.i(TAG, helper.readAUser(1).toString()); //顯示id為1的用戶
user1.setAge(30); //將年齡改為30
helper.updateAUser(user1); //更新數(shù)據(jù)庫
Log.i(TAG, helper.readAUser(1).toString()); //顯示id為1的用戶
helper.deleteAUser(user1.getId()); //刪除user1
Log.i(TAG, helper.readAUser(1).toString()); //顯示id為1的用戶
結(jié)果
上面的代碼中诫睬,分別打印了三次log帕涌。
第一次使用id為1的用戶蚓曼;
第二次是年齡被修改為30的用戶;
第三次是被刪除的用戶纫版,因為用戶不存在了,所以沒有第三條log
(由于helper.readAUser(1)沒有獲取到數(shù)據(jù)癞己,返回null痹雅,接著使用了toString()出現(xiàn)空指針異常,閃退了绩社,做了一個反面教材~~)愉耙。
不管怎么說,這次的目的達(dá)到了绘盟,增刪查改都o(jì)k了悯仙。
小結(jié)
使用SQLite就是在本地建了一個數(shù)據(jù)庫吠卷,使用數(shù)據(jù)庫中的表來保存數(shù)據(jù)祭隔。SQLite對數(shù)據(jù)的操作十分靈活,不過相比SharedPreferences和File在使用上要復(fù)雜一些千贯,而且要一點的數(shù)據(jù)庫基礎(chǔ)搞坝。
附:DatabaseHelper完整代碼
package com.nostra13.universalimageloader.sample;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Gavin on 2016/5/30.
*/
public class DatabaseHelper extends SQLiteOpenHelper {
/**
* 數(shù)據(jù)庫版本,需要升級數(shù)據(jù)庫時只要加一即可
*/
private static final int DATABASE_VERSION = 1;
/**
* 數(shù)據(jù)庫名
*/
private static final String DATABASE_NAME = "mySQLite.db";
/**
* 構(gòu)造方法
* 每次創(chuàng)建DatabaseHelper對象時敦第,若本應(yīng)用無該數(shù)據(jù)庫店量,則新建數(shù)據(jù)庫并調(diào)用onCreate方法融师;
* 若該數(shù)據(jù)庫已創(chuàng)建則直接使用已存在的數(shù)據(jù)庫且跳過onCreate方法
* factory : 當(dāng)打開的數(shù)據(jù)庫執(zhí)行查詢語句的時候 會創(chuàng)建一個Cursor對象, 這時會調(diào)用Cursor工廠類 factory, 可以填寫null默認(rèn)值
* @param context 上下文
*/
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* 創(chuàng)建數(shù)據(jù)庫是時調(diào)用(只被調(diào)用一次)
* @param db 數(shù)據(jù)庫
*/
@Override
public void onCreate(SQLiteDatabase db) {
//創(chuàng)建user表,屬性:id(用戶id舀射,主鍵)、name(姓名)庙曙、age(年齡)
db.execSQL("CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(10),age INTEGER)");
}
/**
* 跟新數(shù)據(jù)庫時調(diào)用
* @param db 數(shù)據(jù)庫
* @param oldVersion 舊版本號
* @param newVersion 新版本號
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//升級user表捌朴,添加性別
//db.execSQL("ALTER TABLE user ADD COLUMN gender VARCHAR(2)");
}
/**
* 插入一條數(shù)據(jù)
* @param user 用戶對象
*/
public void insertAUser(User user) {
//如果要對數(shù)據(jù)進(jìn)行更改张抄,就調(diào)用此方法得到用于操作數(shù)據(jù)庫的實例,該方法以讀和寫方式打開數(shù)據(jù)庫
SQLiteDatabase database = getWritableDatabase();
//向user表插入一條數(shù)據(jù)
database.execSQL(
"INSERT INTO user(name, age) VALUES(?,?)",
new Object[]{user.getName(), user.getAge()});
}
/**
* 更新一條用戶數(shù)據(jù)
* @param user 用戶對象
*/
public void updateAUser(User user) {
SQLiteDatabase database = getWritableDatabase();
//根據(jù)id更新一條數(shù)據(jù)
database.execSQL(
"UPDATE user SET name=?, age=? WHERE id=?",
new Object[]{user.getName(), user.getAge(), user.getId()});
}
/**
* 根據(jù)id刪除一條數(shù)據(jù)
* @param id 用戶id
*/
public void deleteAUser(Integer id) {
SQLiteDatabase database = getWritableDatabase();
//根據(jù)id刪除一條數(shù)據(jù)
database.execSQL("DELETE FROM user WHERE id=?",
new Object[]{id});
}
/**
* 獲取整個用戶列表
* @return
*/
public List<User> readAllUser() {
SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM user", new String[]{});
List<User> list = new ArrayList<User>();
while (cursor.moveToNext()) {
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndex("id")));
user.setName(cursor.getString(cursor.getColumnIndex("name")));
user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
list.add(user);
}
cursor.close();
return list;
}
/**
* 讀取一條數(shù)據(jù)
* @param id 用戶id
* @return 用戶對象
*/
public User readAUser(Integer id) {
//如果只對數(shù)據(jù)進(jìn)行讀取署惯,建議使用此方法
SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.rawQuery(
"SELECT * FROM user WHERE id=?",
new String[]{id.toString()});
if (cursor.moveToFirst()) {
//讀取數(shù)據(jù)极谊,并返回
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndex("id")));
user.setName(cursor.getString(cursor.getColumnIndex("name")));
user.setAge(cursor.getInt(cursor.getColumnIndex("age")));
cursor.close();
return user;
} else {
//未讀出數(shù)據(jù),返回空數(shù)據(jù)
return null;
}
}
}