1 SQLite數據庫
1.1 概念及基礎知識
【
Sqlite數據庫
作用:
用於存儲n張數據表
數據表的作用:爲了同時清晰存儲多條複雜數據,如存儲一張學生信息表
Ø sqlite數據庫支持的數據類型(5種類型)
1) null 空
2) integer 整型
3) real 浮點型
4) text/varchar 字符串
5) blob 二進制
Ø sqlite支持的約束條件
1) primarykey:主鍵約束,非空且唯一
每張表都應該設置一個主鍵,找不到合適的主鍵的話,可以添加一個自增長列(只能是整型)來作爲表的主鍵。
一張表最多只能有一個主鍵
2) notnull:非空約束
3) unique:唯一約束,可以爲空
4) check:檢查約束
5) default:默認約束
6) foreign key:外鍵約束
ü 主要用於維護引用的完整性(默認沒有開啓,要想使用必須手動開啓)
ü 手動開啓外鍵約束:PRAGMAforeign_keys = ON
ü 外鍵列的值必須在主鍵列中存在,否則就會出錯。
ü 語法:字段名 數據類型 references表名(字段名)
特點:
手機端應用軟件通常使用的數據庫,輕量級數據庫,只能處理一些數據的簡單的增刪改查操作
使用分類:
1. 操作本工程自己的數據庫
即自己創建數據庫,數據表,自己在本工程內進行增刪改查
2. 已有現成的數據庫文件,直接操作現成的數據庫文件
在本工程內創建數據庫以及數據表
1. 創建SqliteOpenHelper的子類
2. 重寫子類中的相關方法
publicMyHelper(Context context) {
super(context,"abc.db",null,1);
// TODO Auto-generated constructor stub
}
/**
*SQLiteDatabase數據庫對象的封裝類,
* 通過此類執行sql語句
* 在此方法中通常執行創建表的操作
*
* 此方法的運行特點:
* 當通過當前的Helper對象調用getReadableDatabase或者getWriteableDatabase方法時
* 回去判斷在data/data/程序包名/databases文件夾內是否存在數據庫文件,如果
* 不存在運行此方法,如果存在,則不運行
* */
@Override
public void onCreate(SQLiteDatabasedb) {
// 創建表的實現方式:執行創建表的sql語句
/*
*create table 表名(列名 列中數據的類型 primary key autoincrement,列名2 列中數據的類型,... )
*primary key 主鍵列
*autoincrement 列中數據自動增長
*text 字符串類型
**/
Log.i("====", "===== onCreate");
db.execSQL("createtable ay (_id integer primary key autoincrement,name text,age integer)");
}
//一旦數據庫的版本號發生變化時調用的方法
@Override
public void onUpgrade(SQLiteDatabasedb, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
Log.i("====", "===== onUpgrade"+oldVersion + " "+newVersion);
// db.execSQL("droptable ay"); //刪除表
//
// onCreate(db);
}
什麼時候使用數據庫??
當需要在本地存儲多條複雜數據時,可以考慮使用數據庫進行管理
如存儲n個學生的信息
1. 自產自銷式
在本工程內部創建自身的數據庫,由本工程自己去進行相關的增刪改查操作
想要實現以上目標,必須通過SQLiteOpenHelper的類來實現
關於數據庫中增刪改查操作的實現:
/*
* 通常情況下,建議將所有的數據庫操作封裝爲該類中的自定義方法,
* 方便後期統一修改管理
* */
public classMyHelper extends SQLiteOpenHelper {
/*
* 爲後期初始MyHelper對象方便一些,並且,通常情況下, 多次創建MyHelper對象時
* 指定的數據庫名字和版本號都是不變的,因此修改構造方法
* */
SQLiteDatabase db;
public MyHelper(Context context) {
/*
*2. 指定數據庫文件的名字
*4. 數據庫的版本號
**/
super(context, "test.db",null, 1);
// TODO Auto-generated constructor stub
db= getReadableDatabase();
}
//數據庫初始化時運行的方法,只會在數據庫文件不存在時運行一次,
//一旦數據文件存在,不再運行
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
Log.i("===", "===== onCreate onCreate");
/*
*通常數據庫中不允許存在同名的表
*因此添加if not exists關鍵字,用於實現當數據庫中不存在指定的ay表時創建表
*如果已存在,不再繼續創建
**/
db.execSQL("createtable if not exists ay (_id integer primary key autoincrement,name text,ageinteger)");
}
//當數據庫的版本發生變化時運行的方法,針對於版本變化,必須是newVersion>oldVersion
@Override
public void onUpgrade(SQLiteDatabase db, intoldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("droptable if exists ay");
onCreate(db);
}
/*
* 通常情況下,建議將所有的數據庫操作封裝爲該類中的自定義方法,
* 方便後期統一修改管理
* */
//1. 自定義方法,用於添加數據
public void add (String name,int age){
/*
*添加數據的sql語句
*insert into 表名(列名1,列名2...) values (值1,值2...)
*values中可以通過指定?先代表佔位,稍後再給這個位置賦值
*稍後通過execSQL方法的參數二的Object數組給每一個問號賦值
*即前面的sql語句中有多少個?,Object數組中就應該有多少個元素
**/
db.execSQL("insertinto ay (name,age) values (?,?)", new Object[]{name,age});
}
//自定義方法,用於刪除數據
public void delete (int _id){
/*
*刪除的sql語句
*
*delete from 表名 刪除表中所有的數據
*delete from 表名 where 條件表達式 刪除符合條件的數據
*
**/
db.execSQL("deletefrom ay where _id = "+_id);
}
//自定義方法,用於實現數據的修改
public void update (int id,String name,intage){
/*
*修改的sql語句
*update 表名 set 列名1 = 值1,列名2 = 值2.... 修改表中的所有數據
*update 表名 set 列名1 = 值1,列名2 = 值2.... where 條件表達式 修改表中符合條件的數據
**/
db.execSQL("updateay set name = ?, age=? where _id = ?", new Object[]{name,age,id});
}
}
在MyHelper中定義好方法之後,只需在Activity中需要的位置通過MyHelper對象調用相應方法即可
】
1.2 Cursor類
【
列相關操作
getColumnCount():獲取總列數
getColumnName(intcolumnIndex):獲取指定位置的列名
getColumnIndex(StringcolumnName):獲取列的索引位置
isNull(intcolumnIndex):指定位置的列是否爲null
getType(intcolumnIndex):獲取指定位置列的數據類型
getType(intcolumnIndex):獲取指定位置列的數據類型
Cursor.FIELD_TYPE_INTEGER:int 類型
Cursor.FIELD_TYPE_FLOAT:float類型
Cursor.FIELD_TYPE_STRING:String類型
Cursor.FIELD_TYPE_BLOB:blob類型,即對象或二進制數據類型
記錄相關操作
getCount():獲取總記錄數
getString(intcolumnIndex):獲取指定列的String類型數據
getInt(intcolumnIndex):獲取指定列的long類型數據
getLong(intcolumnIndex):獲取指定列的long類型數據
getFloat(intcolumnIndex):獲取指定列的float類型數據
getDouble(intcolumnIndex):獲取指定列的double類型數據
位置移動
booleanmoveToNext():下一行移動
booleanmoveToPrevious():移到初始位置,第一條記錄的上方
booleanmoveToPosition(int position):移動到指定位置
booleanmoveToFirst():移到第一條位置
booleanmoveToLast():移動到最後一條位置
move(intoffset):從當前位置向上或下移動n行,負值是向上移動,反之向下
】
1.3 重點數據的查詢操作
【
查詢:語法:select 列名1,列名2,...from 表名 [where 條件][group by 列名]
[having 條件][order by 列名 asc/desc][limit 初始位置,查詢個數]
查詢的實現:
//自定義方法,用於查詢全表的所有數據
public ArrayList<Student> getAllStus (){
/*
*查詢全表的sql語句:
*select * from 表名
**/
//爲了能夠獲取查詢的結果,選擇使用rawQuery方法的到查詢結果
/*
*參數1:要執行的查詢的sql語句
*參數2:參數1 中如果存在?,通過此參數給?賦值,如果參數1中沒有?,填null即可
**/
Cursor cursor =db.rawQuery("select * from ay", null);
ArrayList<Student> list = new ArrayList<Student>();
/*
*通過Cursor對象獲取查詢數據,並將查詢數據添加到集合中,用於返回
*Cursor 遊標
*特點:默認是指向查詢結果表的第一行的上方,必須每次向下移動一行,每次移動後Cursor
*對象中可獲取當前行的所有數據
*
*數據庫中獲取查詢結果的原則:通過Cursor確定行數,再通過列名確定列數,即可將指定行指定列中的數據取出
**/
/*
*moveToNext方法用於讓Cursor向下挪動一行,並且獲取該行數據
*一旦返回值爲false,代表已經移動到末尾,沒有更多的數據了
**/
while(cursor.moveToNext()){
/*
* 通過cursor調用get方法獲取本行指定類中的數據
* 方法的參數要求填寫該列對應的列索引
* 可以通過getColumnIndex方法獲取指定列名對應的列索引
* */
String name = cursor.getString(cursor.getColumnIndex("name"));
int age =cursor.getInt(cursor.getColumnIndex("age"));
list.add(new Student(name, age));
}
return list;
}
//查詢全表數據,按照指定的模式排序,如按年齡排序,年齡大的靠前
public ArrayList<Student> getAllSortStus (){
/*
*查詢全表的sql語句 (帶排序效果):
*select * from 表名 order by 列名 asc或者desc
*asc 根據指定列中的值升序排列
*desc 根據指定列中的值降序排列
**/
Cursor cursor = db.rawQuery("select* from ay order by age desc", null);
ArrayList<Student> list = new ArrayList<Student>();
while(cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
list.add(new Student(name, age));
}
return list;
}
//帶條件的查詢
public ArrayList<Student> getStu (String names){
/*
*查詢表中指定的數據:
*select * from 表名 where 條件表達式 【 order by 列名 asc或者desc】
*【】代表可選擇不寫的內容
**/
/*
* 注意:一旦查詢條件的值一個字符串類型的數據,那麼建議用?替換此值,否則直接進行字符串拼接的話
* 需要給此數據添加‘’引起來纔可以
**/
Cursor cursor =db.rawQuery("select * from ay where name = ?", new String[]{names});
ArrayList<Student> list = new ArrayList<Student>();
while(cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
list.add(new Student(name, age));
}
return list;
}
//模糊查詢
//如查詢表中所有名字姓李的學生
public ArrayList<Student> likeStu (String names){
/*
*模糊查詢:
*select * from 表名 where 列名 like 值
*
*值:
* % + 數據 查詢的條件字符串必須以數據結尾 -- endsWith
* 數據 + % 查詢的條件字符串必須以數據開頭 ---startsWith
* %+數據+% 只要包含查詢的條件字符串即可---contains
*
**/
/*
* 注意:一旦查詢條件的值一個字符串類型的數據,那麼建議用?替換此值,否則直接進行字符串拼接的話
* 需要給此數據添加‘’引起來纔可以
**/
Cursor cursor = db.rawQuery("select* from ay where name like ?", new String[]{names+"%"});
ArrayList<Student> list = new ArrayList<Student>();
while(cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
list.add(new Student(name, age));
}
return list;
}
】
1.3.1 通過內置方法實行查詢
【
通過SQLiteDatabase 中封裝好的方法實現數據庫的增刪改查:
增加:
/*
* 1. 要添加數據的表名
* 3. 要添加的數據,ContentValues對象
* 特點:可以存儲多組鍵值對
* 鍵值對中的鍵是表中的列名
* 2. 任意添加表中一個列的列名即可。通過情況下添加主鍵列的名字
* 作用如:
* 指定表中可以爲NULL的列的名字
* 當參數二和參數三同時傳遞null時,會報錯
* 如果參數二爲表中任意列名,參數三爲null時,不會報錯,可以成功添加數據,只不過添加的數據NULL
* */
ContentValuesvalues = new ContentValues();
//代表向表中參數一指定的列中加入參數二傳遞的數據
values.put("names", name);
/*
* 返回值代表新添加的數據對應的id值
* -1 添加失敗
* */
long id = db.insert("tea","_id", values);
刪除:
/*
* 1. table 表名
* 2. 指定刪除的條件
* 3. 參數2的條件中?的值
* 返回值用於代表刪除成功的條數
* */
int num = db.delete("tea", "name = ?", new String[]{name});
修改:
/*
*1. table 表名
*2. 要修改成的數據 ContenValues
*
* 3. 指定修改的條件
* 4. 參數3的條件中?的值
* */
ContentValues values = new ContentValues();
values.put("name", name);
//返回值代表修改成功的條數
db.update("tea", values, "name = ?", new String[]{tiao});
查詢:
/*
* 1. 表名
* 2. String[] 指定要查詢表中的哪些列,
* 如全表中有_id和name兩列,如果只要獲取所用name的值,不需要id的話,可以在數組中直接定“name”
* 如果要查詢所有列,填null
* 3. String ,要與設置查詢條件,不需要寫where,直接寫條件表達式即可
* 沒條件,填null
*
* 4. 如果參數3中有代表佔位的?,那麼此參數用於設置?的值
*
* 5,6 指定分組的條件,即設置where 查詢條件的另一種方式
* 7. 指定排序條件
* */
Cursor cursor = db.query("tea", null, null, null, null, null, null);
//要查新name爲abc的值,query方法該如何封裝??
// Cursor cursor =db.query("tea", null, "name = ?", new String[]{"abc"},null, null, "name asc");
】
1.4 通過方法實現增刪改查操作
【
相對於db.execSql來說,更新、刪除、插入操作能夠返回相應的數字影響條數,能夠響應是否操作成功了!
=插入= // 對於insert方法插入返回的是插入數據對應的id
long id= db.insert("tea", null,values);
=刪除= intnum = db.delete("tea", "name=?", new String[] { name });
=更新= intnum = db.update("tea", values, "name=?", new String[] {name });
】
示例代碼:
【
public class MyHelper extends SQLiteOpenHelper{
SQLiteDatabasedb;
public MyHelper(Context context) {
super(context, "stu.db",null, 1);
// TODO Auto-generated constructor stub
db = getReadableDatabase();
}
@Override
public voidonCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("create table if not exists tea(_id integer primarykey autoincrement,name text)");
}
@Override
public voidonUpgrade(SQLiteDatabase db, intoldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("drop table if exists tea");
onCreate(db);
}
// 插入數據
public voidadd(String name) {
ContentValuesvalues = new ContentValues();
values.put("name",name);
// 對於insert方法插入返回的是插入數據對應的id
long id= db.insert("tea",null, values);
}
// 刪除數據
public voiddelete(String name) {
int num= db.delete("tea","name=?", new String[] { name });
}
// 更新數據
public voidupdate(String name) {
ContentValues values = new ContentValues();
values.put("name", name + name);
int num = db.update("tea", values, "name=?",new String[] {name });
}
// 查詢數據
public ArrayList<String> query(Stringnames) {
ArrayList<String>data = new ArrayList<String>();
// columns:過濾的列名
// selection:查詢條件
// selectionArgs:條件中所帶的佔位符參數值
// 全表查詢
//Cursor cursor = db.query("tea", null, null,null, null, null,
// "namedesc");
Cursor cursor =db.query("tea", null, "name=?", new String[]{names},null, null, "name desc");
while(cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
data.add(name);
}
return data;
}
// 全表查詢
public ArrayList<String> getAll() {
ArrayList<String>data = new ArrayList<String>();
// columns:過濾的列名
// selection:查詢條件
// selectionArgs:條件中所帶的佔位符參數值
// 全表查詢
Cursorcursor = db.query("tea",null, null,null, null,null, null);
while (cursor.moveToNext()) {
Stringname = cursor.getString(cursor.getColumnIndex("name"));
data.add(name);
}
return data;
}
}
】
1.5 數據庫中完成對圖片的操作
【
如何在數據庫中完成對圖片的存取操作??
1. 在創建表時,如果需要讓某一列可以存儲圖片,那麼只需將此列的類型設置爲blob類型即可
/*
* blob 大數據類型,實際上就是byte[]類型,
* 此類型專門用來存儲一些圖片或者音頻文件等
* */
db.execSQL("createtable img (_id integer primary key autoincrement, name text, ima blob)");
2. 在存入圖片時:
//將bit對象轉爲byte數組
ByteArrayOutputStreambos = newByteArrayOutputStream();
bit.compress(CompressFormat.PNG,100, bos);
byte[] b = bos.toByteArray();
ContentValues values = new ContentValues();
values.put("name", name);
values.put("ima", b);
db.insert("img", "_id", values);
3. 在取出圖片時:
Cursorc = db.query("img", null, "_id="+1, null, null, null, null);
if(c.moveToNext()) {
byte[] b =c.getBlob(c.getColumnIndex("ima"));
return BitmapFactory.decodeByteArray(b,0, b.length);
}
】
示例代碼:
【
public class ImageHolderDB extends SQLiteOpenHelper {
private SQLiteDatabase db;
public ImageHolderDB(Context context) {
super(context, "image.db",null, 1);
// TODO Auto-generated constructor stub
db = getReadableDatabase();
}
@Override
public voidonCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
/*
* blob 大數據類型,實際上就是byte[]類型,
* 此類型專門用來存儲一些圖片或者音頻文件等
* */
db.execSQL("create table if not exists img(_id integer primarykey autoincrement,name text,img blod)");
}
@Override
public voidonUpgrade(SQLiteDatabase db, intoldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("drop table if exists img ");
onCreate(db);
}
//向數據庫中添加數據
public voidadd(String name,Bitmap bit){
//將bit對象轉爲byte數組
ByteArrayOutputStreambos = new ByteArrayOutputStream();
bit.compress(CompressFormat.PNG, 100, bos);
byte[] b=bos.toByteArray();
ContentValuesvalues = new ContentValues();
values.put("name", name);
values.put("img", b);
db.insert("img","_id", values);
}
//讀取圖片流對象
public Bitmap getImage(){
Cursorcursor = db.query("img",null, "_id="+1,null, null,null, null);
if(cursor.moveToNext()){
byte[] b=cursor.getBlob(cursor.getColumnIndex("img"));
return BitmapFactory.decodeByteArray(b,0, b.length);
}
return null;
}
//測試大批量的數據批量插入時的效率問題測試
/**
* 執行SQl語句形式execSQL
*/
public voidaddBySql(){
long start = System.currentTimeMillis();
for(inti=0;i<1000;i++){
db.execSQL("insertinto img(name) values(?)",newObject[]{"sql item"+i});
}
long end =System.currentTimeMillis();
Log.i("===", "===== sql time"+(end-start));
}
/**
* 執行Insert方法
*/
public voidaddByInsert(){
long start = System.currentTimeMillis();
for(inti=0;i<1000;i++){
ContentValuesvalues = new ContentValues();
values.put("name", "insertitem"+i);
db.insert("img","_id", values);
}
long end = System.currentTimeMillis();
Log.i("===", "==== insert time"+(end-start));
}
事務運用:對於批量數據的操作,運行速度加較快
public void ByTransAction(){
long start =System.currentTimeMillis();
db.beginTransaction(); //開啓事務
try {
for(int i=0;i<1000;i++){
db.execSQL("insertinto img(name) values (?)",new Object[]{"sql item"+i});
}
db.setTransactionSuccessful(); //給事務提供一個成功標識
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//結束事務
db.endTransaction();
long end = System.currentTimeMillis();
Log.i("===", "==== transaction time "+(end-start));
}
}
】
1.6 數據庫中事務的作用
【
數據庫中事務的作用:
1. 當大批量操作數據庫時,如添加1000條數據,可以大大提高添加的速度
2. 可以確保大批量的操作要麼全部執行成功,要麼全部執行無效
事務的使用方式:
1. 在開始執行數據庫操作之前通過db調用beginTransaction方法開啓事務
2. 通過try catch將數據庫操作部分代碼包裹起來
3. 在try語句塊的最末尾添加db. setTransactionSuccessful方法設置事務的成功標識
4. 在try catch語句後通過db調用endTransaction方法結束事務即可
代碼如:
db.beginTransaction(); //開啓事務
try {
for (int i=0;i<1000;i++) {
db.execSQL("insert into img (name) values (?)",new Object[]{"sqlitem"+i});
// if (i==100) {
// db.execSQL("insertinto imgs (name) values (?)",new Object[]{"sqlitem"+i});
// }
}
db.setTransactionSuccessful(); //給事務提供一個成功標識
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//結束事務,在結束時,會自動判斷是否有記錄過成功標識,如沒有則將所有beginTransaction之後執行的代碼//效果全部清空回滾掉
db.endTransaction();
】
1.7 提供給數據庫使用的適配器
【
提供給數據庫使用的適配器:
SimpleCursorAdapter
特點:
1. 數據源爲Cursor類型
2. 不能控制blob類型數據的顯示
使用方式:
通過構造方法初始化適配器後,通過setAdapter方法設置適配器即可
/*
* 1.Context 環境
* 2. int layout,用於指定列表中每個item條目對應的佈局文件
* 3.Cursor類型,即適配器顯示的數據源
* 注意:數據源的位置可以傳null,一旦穿null的話,並不會崩潰,而是代表列表中不顯示任何數據
* 4. String[] from 數據從哪來 ,添加表中的列名
* 5. int[] to 數據到哪去顯示,佈局中控件的id
* 6. flag標識
*
* 缺陷:不能顯示圖片
* */
adapter = new SimpleCursorAdapter(this, R.layout.item, c, new String[]{"name","age"}, new int[]{R.id.textView1,R.id.textView2}, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
更新SimpleCursorAdapter適配器的方法:
1. 得到新的Cursor查詢結果
2. 通過adapter調用swapCursor方法更新數據源
3. 通過adapter調用notifyDataSetChanged方法刷新適配器的顯示
Cursor c = helper.getData(currentPage*20);
//交換數據源,更新數據源
adapter.swapCursor(c);
adapter.notifyDataSetChanged();
查詢數據表中指定位置指定條數的數據:
/*
* limit 從表中截取指定行數的數據
* limit後跟兩個數據
* 其中第一個數字:起始行數的position位置
* 第二個數字:要截取多少行數據
* */
return db.rawQuery("select * from aylimit ?,?", newString[]{start+"","20"}); //分頁
】
1.8 SimpleCursorAdapter與分頁的實現
【
public class MyHelper extends SQLiteOpenHelper {
Contextcontext;
private SQLiteDatabase db;
public MyHelper(Context context) {
super(context, "name.db",null, 1);
// TODO Auto-generated constructor stub
this.context= context;
db = getReadableDatabase();
}
@Override
public voidonCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("create table if not exists ay(_id integer primarykey autoincrement,name text,age text,img blob)");
// 在此處添加數據庫中的初始數據
db.beginTransaction();
try {
ByteArrayOutputStreambos = new ByteArrayOutputStream();
Bitmapbit = BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_launcher);
bit.compress(CompressFormat.PNG, 100, bos); //將Bitmap對象轉換爲內存輸出流對象
for (inti = 0; i < 3000; i++) {
ContentValuesvalues = new ContentValues();
values.put("name", "name"+ i);
values.put("age", "age"+ i);
values.put("img", bos.toByteArray());
db.insert("ay", "_id",values);
}
db.setTransactionSuccessful();
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
db.endTransaction();
}
@Override
public voidonUpgrade(SQLiteDatabase db, intoldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("drop table if exists ay");
onCreate(db);
}
// 實現分頁效果
public Cursor getData(int start) {
return db.rawQuery("select * fromay limit ?,?", new String[]{
start+ "", "20" });
}
// 獲取分得的總頁數
public intgetTotalPage() {
/*
* Cursor c = db.rawQuery("select * from ay",null); //獲取查詢結果的個數 int
* totalNum = c.getCount();
*/
// 查詢ay表中的數據個數,並將數據個數賦值給c列
Cursorc = db.rawQuery("selectcount(*) as count from ay", null);
c.moveToNext();
int totalNum = c.getInt(c.getColumnIndex("count"));
int totalPage = 0;
if (totalNum % 20 == 0) {
totalPage= totalNum / 20;
}else {
totalPage= totalNum / 20 + 1;
}
return totalPage;
}
}
public class MainActivity extends Activity {
private ListView lv;
//專門配合數據庫使用的適配器,該適配器在指定數據源時。類型爲Cursor類型
SimpleCursorAdapteradapter;
MyHelperhelper;
int currentPage= 145; //用於記錄當前的頁數
int totalPage=0; //用於記錄總頁數
EditTextet_num_page;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv =(ListView) findViewById(R.id.lv_mai_4x);
et_num_page=(EditText) this.findViewById(R.id.et_to_page);
helper = newMyHelper(this);
Cursorc = helper.getData(currentPage*20);
/*
* 1.Context 環境
* 2. int layout,用於指定列表中每個item條目對應的佈局文件
* 3.Cursor類型,即適配器顯示的數據源
* 注意:數據源的位置可以傳null,一旦穿null的話,並不會崩潰,而是代表列表中不顯示任何數據
* 4. String[] from 數據從哪來 ,添加表中的列名
* 5. int[] to 數據到哪去顯示,佈局中控件的id
* 6. flag標識
*
* 缺陷:不能顯示圖片
* */
adapter = new SimpleCursorAdapter(this,R.layout.item, c, new String[]{"name","age"},new int[]{R.id.textView1_4x,R.id.textView2_4x},SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
totalPage = helper.getTotalPage();
}
//按鈕的點擊事件
public voidclick(View v){
switch (v.getId()) {
case R.id.btn_privition: //跳轉到上一頁
if(currentPage>0){
currentPage--;
}
break;
case R.id.btn_next: //跳轉到下一頁
if(currentPage<(totalPage-1)){
currentPage++;
}
break;
case R.id.btn_tiao_page: //跳轉到指定頁
if(TextUtils.isEmpty(et_num_page.getText().toString())){
return;
}
int page_num =Integer.parseInt(et_num_page.getText().toString());
currentPage = page_num;
break;
}
Cursor c =helper.getData(currentPage*20);
//交換數據源,更新數據源
adapter.swapCursor(c);
adapter.notifyDataSetChanged();
}
}
】
1.9 操作SD卡中的數據文件
【
Sqlite數據庫
使用方向二:
直接使用sd卡中現成的數據庫文件進行操作,或者說,直接在指定的sd卡中或本工程中通過此方法創建一個數據庫文件
即不通過使用SqliteOpenHelper對象操作數據庫
通過SqliteDatabase對象調用以下方法實現上述目標
openDatabase(String path, CursorFactory factory, int flags)
參數1:path,數據文件的路徑
參數2:factory,遊標工廠,null代表使用默認的遊標工廠對象
參數3:flags,訪問模式
SQLiteDatabase.OPEN_READONLY:以只讀的方式打開數據庫
SQLiteDatabase.OPEN_READWRITE:以可讀寫的方式打開數據庫
SQLiteDatabase.CREATE_IF_NECESSARY:當數據庫不存在時,創建數據庫
SQLiteDatabase.NO_LOCALIZED_COLLATORS:打開數據庫時,不根據本地化語言對數據進行排序
openOrCreateDatabase(File file, CursorFactory factory)
等價於 SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), null,SQLiteDatabase.CREATE_IF_NECESSARY);
Cursor對象的常用方法:
Cursor類
列相關操作
getColumnCount():獲取總列數
getColumnName(intcolumnIndex):獲取指定位置的列名
getColumnIndex(StringcolumnName):獲取列的索引位置
isNull(intcolumnIndex):指定位置的列是否爲null
getType(intcolumnIndex):獲取指定位置列的數據類型
getType(intcolumnIndex):獲取指定位置列的數據類型
Cursor.FIELD_TYPE_INTEGER:int 類型
Cursor.FIELD_TYPE_FLOAT:float類型
Cursor.FIELD_TYPE_STRING:String類型
Cursor.FIELD_TYPE_BLOB:blob類型,即對象或二進制數據類型
記錄相關操作
getCount():獲取總記錄數
getString(intcolumnIndex):獲取指定列的String類型數據
getInt(intcolumnIndex):獲取指定列的long類型數據
getLong(intcolumnIndex):獲取指定列的long類型數據
getFloat(intcolumnIndex):獲取指定列的float類型數據
getDouble(intcolumnIndex):獲取指定列的double類型數據
位置移動
booleanmoveToNext():下一行移動
booleanmoveToPrevious():向上一行移動
booleanmoveToPosition(int position):移動到指定位置
booleanmoveToFirst():移到第一條位置
booleanmoveToLast():移動到最後一條位置
move(intoffset):從當前位置向上或下移動n行,負值是向上移動,反之向下
通過SqliteOpenHelper獲取的數據庫與通過openDatabase方法獲取的數據庫有什麼區別??在什麼情況下應該使用SqliteOpenHelper,在什麼情況下可以使用openDatabase方法??
通過兩種方式得到db對象之後,對db對象執行的增刪改查的方式都是一樣的
不同點在於: SqliteOpenHelper是控制本工程內自身的數據庫
openDatabase 是打開sd卡中的數據庫
總結起來:當需要操作本工程內的數據庫,選擇用SqliteOpenHelper
如果只是操作sd卡中的數據庫,選用openDatabase方法
SimpleCursorAdapter的使用補充注意:
1. 該適配器中顯示的Cursor對象對應的那張表的主鍵列的名字必須是_id
2. 在查詢得到Cursor對象時,必須查詢主鍵類的值,
如表中:_id,name,age 查詢時只查name列,不行,SimpleCursorAdapter
會崩潰
】
示例代碼:
【
public class MainActivity extends Activity {
SQLiteDatabase db;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public voidclick(View v) {
switch (v.getId()) {
case R.id.button1:
// 獲取sd卡中數據庫文件對象
db = SQLiteDatabase.openDatabase(Environment
.getExternalStorageDirectory().getAbsolutePath()
+"/testss.db", null,SQLiteDatabase.CREATE_IF_NECESSARY);
//此方法的作用相當於調用了flags設置爲SQLiteDatabase.CREATE_IF_NECESSARY的openDatabase方法的作用
//SQLiteDatabase.openOrCreateDatabase(file, factory);
break;
case R.id.button2:
//創建表
db.execSQL("createtable ay(_id integer primary key autoincrement,name text)");
break;
case R.id.button3:
//添加數據
db.execSQL("insertinto ay(name) values(?)",newObject[]{System.currentTimeMillis()+"a"});
break;
case R.id.button4:
//查詢數據庫中的數據
Cursorcur = db.rawQuery("select* from ay", null);
while(cur.moveToNext()){
Stringname = cur.getString(cur.getColumnIndex("name"));
Log.i("===", "=====all data name "+name);
}
//查詢所有奇數行的數據
for(inti=1;i<cur.getCount(); i+=2){
cur.moveToPosition(i);
Stringname = cur.getString(cur.getColumnIndex("name"));
Log.i("===", "====name " +name);
}
break;
}
}
}
】