Android之SQLite數據庫的使用

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[] 指定要查詢表中的哪些列,

            * 如全表中有_idname兩列,如果只要獲取所用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);

          

           //要查新nameabc的值,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_NECESSARYopenDatabase方法的作用

                            //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;

 

                   }

         }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章