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;

 

                   }

         }

}

 

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值