• 【Android】13.1 用Android自带的API访问SQLite数据库


    分类:C#、Android、VS2015;

    创建日期:2016-02-26

    一、简介

    这一节我们先来看看如何直接用Android自带的API创建和访问SQLite数据库。

    1、创建SQLite数据库

    Android提供了一个SQLiteOpenHelper类(在Android.Database.Sqlite命名空间下),你只需要创建一个继承自SQLiteOpenHelper的类,就可以利用它轻松创建Sqlite数据库。

    在继承自SQLiteOpenHelper的类中,要求至少需要实现下面的3个方法:

    • 在构造函数中调用父类的构造函数。这个方法需要4个参数:

             context:上下文环境(例如,一个Activity)

             DatabaseName:数据库名

             ICursorFactory:一个可选的游标工厂(通常将其设置为null)

             DatabaseVersion:一个整数,表示你的数据库版本。

    • 重写OnCreate方法。在这个重写的方法中,你可以利用SQLiteDatabase对象创建表和初始化数据。该方法可确保创建数据库的SQL语句只运行一次,这种功能是在SQLiteOpenHelper类中实现的。
    • 重写OnUpgrage方法。该方法有3个参数:一个 SQLiteDatabase 对象,一个旧的版本号,一个新的版本号。利用它可以把一个数据库从旧的模型转变到新的模型。

    具体用法见本节的示例。

    数据库帮助器类创建完毕后,就可以在Activity中调用GetReadableDatabase()或者GetWriteableDatabase()方法获取SQLiteDatabase实例,具体调用哪个方法,取决于你是否需要改变数据库的内容。

    例如:

    public class MainActivity : Activity

    {

        private MyDb1Help db;

        private ICursor cursor;

        ……

        protected override void OnCreate(Bundle bundle)

        {

            ……

            db = new MyDb1Help(this);

            cursor = db.ReadableDatabase.RawQuery("SELECT * FROM MyTable1", null);

            ……

        }

    }

    上面这段代码会返回一个SQLiteDatabase类的实例,接下来就可以使用这个对象查询或者修改数据库了。

    当你完成了对数据库的操作(例如你的 Activity 已经关闭),需要调用 SQLiteDatabase 的 Close() 方法释放掉数据库连接。

    具体用法见本节的示例代码。

    2、创建表

    可通过调用 SQLiteDatabase实例的 execSQL() 方法执行 DDL 语句。例如:

    db.execSQL("CREATE TABLE MyTable1 (……)"); //见例子中的具体代码

    这条语句创建一个名为 MyTable1 的表,表有一个列名为“_id”,并且是主键,该列的值是会自动增长的整数(插入一行时SQLite会给这一列自动赋值),另外创建的列还有:name和age。

    注意:SQLiteDatabase要求自动增量的字段名必须是“_id”而不是“id”或其他名称。

    删除表时,可通过 execSQL() 方法执行 DROP TABLE 语句。

    3、编辑数据(添加、删除、修改)

    创建了数据库和表以后,就可以对数据表进行添加、删除、修改等操作了。

    Android API提供了两种编辑数据的方式。

    (1)方式1

    方式1:使用 execSQL() 方法执行 INSERT、UPDATE、DELETE等语句来更新表数据。execSQL() 方法适用于所有不返回结果的 SQL 语句。例如:

    db.execSQL("INSERT INTO MyTable1 (name, age) VALUES ('Zhang san', 24)");

    (2)方式2

    方式2:使用SQLiteDatabase对象的Insert()、Update()、Delete()方法。这些方法把SQL语句的一部分作为参数。例如:

    ContentValues cv=new ContentValues();

    cv.put(Constants.TITLE, "example title");

    cv.put(Constants.VALUE, SensorManager.GRAVITY_DEATH_STAR_I);

    db.insert("mytable", getNullColumnHack(), cv);

    Update()方法有四个参数,分别是表名,表示列名和值的 ContentValues 对象,可选的 WHERE 条件和可选的填充 WHERE 语句的字符串,这些字符串会替换 WHERE 条件中的“?”标记。update() 根据条件,更新指定列的值,所以用 execSQL() 方法可以达到同样的目的。

    WHERE 条件和其参数和已经使用过的其他 SQL APIs 类似。例如:

    string[] parms=new String[] {"this is a string"};

    db.update("widgets", replacements, "name=?", parms);

    delete() 方法的用法和 update() 类似,使用表名、可选的 WHERE 条件和相应的填充 WHERE 条件的字符串。

    4、查询数据

    与 INSERT、UPDATE、DELETE类似,也有两种方式使用 SELECT 从 SQLite 数据库检索数据:

    第1种方式是使用 RawQuery() 直接调用 SELECT 语句;

    第2种方式是使用 Query() 方法构建一个查询。

    (1)RawQuery()

    RawQuery() 是最简单的查询数据的方法,通过这个方法可直接传递 SQL的 SELECT 语句。例如:

    ICursor c=db.rawQuery(

    "SELECT name FROM sqlite_master WHERE type='table' AND name='mytable'", null);

    上面的代码查询 SQLite 系统表(sqlite_master)检查 table 表是否存在。返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。

    但是,如果查询是动态的,使用这个方法会非常复杂。例如,当需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。

    (2)Query()

    query() 方法用SELECT 语句的内容作为该方法的参数。比如:要查询的表名、要获取的字段名、WHERE 条件、用包含可选的位置参数去替代 WHERE 条件中位置参数的值、GROUP BY 条件、HAVING 条件等。

    除了表名,其他参数都可以是 null。所以,以前的代码段可以可写成:

    String[] columns={"ID", "inventory"};

    String[] parms={"snicklefritz"};

    Cursor result=db.query("widgets", columns, "name=?",parms, null, null, null);

    二、SimpleCursorAdapter类

    Android专门提供了一个简单的游标适配器类(SimpleCursorAdapter),利用该类可以从一个SQLite 数据库中查询数据并将其显示出来,其用法和ArrayAdapter相似。

    SimpleCursorAdapter的用法很简单,只需要创建该类的实例并在构造函数中提供所需的参数 (例如游标和布局的信息),然后将查询结果分配给视图(例如ListView)即可。

    SimpleCursorAdapter类的构造函数参数有:

    Context:使用哪个Activity

    Layout:布局文件中显示对应数据行的资源ID

    ICursor:SQLite查询返回的游标。

    From string array:游标中包含的字符串列。

    To integer array:控件中显示对应行的id整型数组,游标会自动将当前读取的列绑定到这些对应的id表示的行上。

    from和to必须有相同数量的条目,这是因为需要在“数据源”和“控件”之间建立一个一对一的映射:

    // 与布局控件对应的列

    string[] fromColumns = new string[] {"name"};

    int[] toControlIDs = new int[] {Android.Resource.Id.Text1};

    // 使用SimpleCursorAdapter创建适配器

    listView.Adapter = new SimpleCursorAdapter (this, Android.Resource.Layout.SimpleListItem1, cursor,

    fromColumns,

    toControlIDs);

    在SimpleCursorAdapter的构造函数中,必须为cursor读取的行指定一个Layout以及指定cursor中的哪一列应该被插入到layout对应行的哪个view中去。

    实例化SimpleCursorAdaptery以后,SimpleCursorAdapter就会使用提供的layout将每一个Columns插入到对应的Views中,并在Cursor中为每一行创建一个View。

    如果改变了可以被Adapter读取的底层数据,可通过NotifyDataSetChanged()通知相关的view刷新数据。

    SimpleCursorAdapter是快速显示SQLite数据库中数据最简单的方式,但是,它只能通过绑定列的值来显示控件,而无法对行进行更改(例如显示/隐藏控件或更改属性等),该适配器一般适用于数据比较少的情况。

    三、示例1—使用SimpleCursorAdapter访问SQLite

    该示例演示SQLiteOpenHelper类和SimpleCursorAdapter类的基本用法。

    1、运行截图

    说明:如果你在运行时发现中文显示为乱码,只需要修改项目中Properties文件夹下的AssemblyInfo.cs文件,将下面的语句:

    [assembly: AssemblyCulture("")]

    改为:

    [assembly: AssemblyCulture("zh-CN")]

    这样就能正常显示简体中文,修改后项目中再也不会出现乱码了。

    image

    2、主要设计步骤

    (1)添加ch1301_Main.axml文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <ListView
            android:id="@+id/ch1301_listView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </LinearLayout>

    (2)添加ch1301MyDb1.cs文件

    using Android.Content;
    using Android.Database.Sqlite;
    
    namespace MyDemos.SrcDemos
    {
        public class ch1301MyDb1 : SQLiteOpenHelper
        {
            public static readonly string sql =
                "CREATE TABLE [MyTable1] (" +
                "[_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE," +
                "[name] TEXT NOT NULL UNIQUE," +
                "[age] INTEGER  NOT NULL)";
            public static readonly string dbName = "MyDb1.db";
            public static readonly int dbVersion = 1;
            public ch1301MyDb1(Context context) : base(context, dbName, null, dbVersion) { }
    
            public override void OnCreate(SQLiteDatabase db)
            {
                db.ExecSQL(sql);
                db.ExecSQL("INSERT INTO MyTable1 (name,age) VALUES ('张三',23)");
                db.ExecSQL("INSERT INTO MyTable1 (name,age) VALUES ('李四',22)");
                db.ExecSQL("INSERT INTO MyTable1 (name,age) VALUES ('王五',19)");
                db.ExecSQL("INSERT INTO MyTable1 (name,age) VALUES ('赵六',21)");
            }
    
            public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
            {
                // 更改数据库版本的操作,如果无版本更改,此处不需要编写任何代码
            }
        }
    }

    (3)添加ch1301MainActivity.cs文件

    using Android.App;
    using Android.OS;
    using Android.Widget;
    using Android.Database;
    
    namespace MyDemos.SrcDemos
    {
        [Activity(Label = "【例13-1】SQLite基本用法1")]
        public class ch1301MainActivity : Activity
        {
            private ICursor cursor;
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                SetContentView(Resource.Layout.ch1301_Main);
                ch1301MyDb1 db = new ch1301MyDb1(this);
                cursor = db.ReadableDatabase.RawQuery("SELECT * FROM MyTable1", null);
                var listView = FindViewById<ListView>(Resource.Id.ch1301_listView1);
                string[] fromColumns = { "name", "age" };
                int[] toControlIDs = new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 };
                listView.Adapter = new SimpleCursorAdapter(this,
                    Android.Resource.Layout.SimpleListItem2,
                    cursor, fromColumns, toControlIDs);
                listView.ItemClick += (s, e) =>
                {
                    var obj = listView.Adapter.GetItem(e.Position);
                    var curs = (ICursor)obj;
                    // 第0~2列的字段名:_id,name,age
                    var text = string.Format("{0}({1}岁)", curs.GetString(1), curs.GetInt(2));
                    Toast.MakeText(this, text, ToastLength.Short).Show();
                };
            }
    
            protected override void OnDestroy()
            {
                cursor.Close();
                base.OnDestroy();
            }
        }
    }
  • 相关阅读:
    《程序猿面试宝典3》大量错误(50+)纠正表
    STM32定时器的预装载寄存器与影子寄存器之间的关系【转】
    Linux虚拟内存和物理地址的理解【转】
    UNIX系统的显示时间何时会到尽头
    assert函数用法总结【转】
    Sizeof与Strlen的区别【转】
    C语言预处理器命令详解【转】
    C#预处理器指令【转】
    I2C总线信号时序总结【转】
    用状态机实现键盘消抖【转】
  • 原文地址:https://www.cnblogs.com/rainmj/p/5219151.html
Copyright © 2020-2023  润新知