天天看点

《OpenGL ES 3.x游戏开发(上卷)》一2.3 手机自带数据库——SQLite

本节书摘来异步社区《opengl es 3.x游戏开发(上卷)》一书中的第2章,第2.3节,作者: 吴亚峰 责编: 张涛,更多章节内容可以访问云栖社区“异步社区”公众号查看。

上一节介绍了如何使用preferences存储简单数据,而复杂的数据就需要存储到文件或数据库中了。android自带了一款轻量级的关系数据库——sqlite,其具有体积小,功能强大等特点,成为嵌入式设备首选的数据库系统。本节将带领读者走进sqlite的世界,学习如何应用sqlite数据库进行数据的增、删、改、查等基本操作。

sqlite是一款满足acid特性的具有完备功能的关系数据库系统,由于其设计目标为轻量级、开源、支持嵌入式使用,因此,目前已经在嵌入式设备领域被广泛采用。其运行需要的系统资源非常少,在嵌入式设备中可能只需要几百kb的内存就够了。

sqlite对主流编程语言的支持也非常全面,如c#、php、java等,同时还支持odbc接口。另外,sqlite的性能也是一流的,在一般应用情况下,其处理速度比mysql、postgresql这两款著名的开源数据库管理系统都快。

提示

虽然sqlite占用的资源非常少,但是其功能、特性与服务器级数据库相比却丝毫不差,这也是sqlite能够受到android系统青睐的主要原因,其部分特性如下所列。

最大可以支持2tb的数据库文件。

占用资源少,一般占用250kb左右。

api非常简单,易于使用。

没有任何额外的依赖,是独立的。

源代码完全开放,可以用于任何用途。

android系统中很多的用户数据都存储在sqlite数据库中,如联系人信息、通话记录、短信等,由此可见sqlite对于android的重要性。

读者要想很好地使用sqlite数据库,必须熟练掌握sql语言。这是由于sql已经事实上成为关系数据库操作的标准语言,市面上的关系数据库几乎无一例外都支持sql。因此,在数据库领域,有这样一句话“学好sql,走遍天下都不怕”。

一般学习数据库相关课程的时候,首先介绍的就是数据库的一些基本操作,如数据的增、删、改、查等。按照惯例,本书也首先简单介绍sqlite数据库的创建、关闭及数据的增加、删除、修改、查询等基本操作,具体如下所列。

想在android下通过java编程对sqlite数据库进行操作,就必须要用到android.database.sqlite包下的sqlitedatabase类,该类提供了对sqlite数据库进行基本操作的所有重要方法。

创建数据库。

创建数据库需要用到的是opendatabase方法,此方法签名为“public static sqlitedatabase opendatabase (string path, sqlitedatabase.cursorfactory factory, int flags)”。其中path为数据库所在的路径;factory为游标工厂;flags为标志,可以用来控制数据库的访问模式。

关闭数据库。

关闭数据库需要用到的是close方法,此方法签名为“public void close()”。在实际开发中数据库使用完毕后,一定不要忘记使用该方法关闭数据库,以防止资源的浪费。

插入数据。

插入数据可以使用insert方法,此方法签名为“public long insert (string table, string nullcolumnhack, contentvalues values)”。其中table为待插入的表名,nullcolumnhack通常设置为null,values为待插入的数据。

更新数据。

更新数据可以使用update方法,其签名为“public int update(string table, contentvalues values, string whereclause, string[] whereargs)”。其中table为待更新的表名;values为待更新内容;whereclause为where子句的内容,用来进行记录筛选;whereargs为where子句的参数。

删除数据。

删除数据可以使用delete方法,其签名为“public int delete (string table, string whereclause, string[] whereargs)”。其中table为要操作的表名;whereclause为where子句的内容,用来进行记录筛选;whereargs为where子句的参数。

查询数据。

查询数据可以使用query方法,其方法签名为“public cursor query (string table, string[] columns, string selection, string[] selectionargs, string groupby, string having, string orderby)”。其中table为要查询的表,columns为要查询的列,selection为过滤记录的子句,selectionargs为过滤的参数值,groupby为分组子句,having为过滤分组的子句,orderby为记录排序子句。

android中被重载了的query方法有多个变体。这里由于篇幅所限,不再赘述,有需要的读者可以自行查阅api或其他相关资料。

执行非查询sql。

对于不太熟悉sql语言的初学者而言,插入、更新、删除数据可以用前面介绍的insert、update、delete方法。但对于熟练掌握sql的开发人员而言,使用execsql方法直接执行相应的sql语句十分方便。

此方法签名为“public void execsql (string sql)”或“public void execsql (string sql, object[] bindargs)”。其中sql为需要执行的sql语句,bindargs为带参数sql语句的参数值数组。

需要注意的是,此方法仅支持执行非查询的sql语句,如create table、 delete、 insert、update等,不能用于执行select语句。

执行查询sql。

对于熟练掌握sql的开发人员而言,会觉得前面介绍的query方法使用过于繁琐。android的设计人员也考虑到了这个问题,提供了支持执行sql查询语句的rawquery方法,其方法签名为“public cursor rawquery (string sql, string[] selectionargs)”。其中sql为要执行的sql查询语句(可以带参数),selectionargs为查询参数的值。

sqlitedatabase类中用于数据库操作的方法还有很多,本书只是介绍了其中一些常用的,若读者有需要可以查阅api或其他相关资料进一步学习。

上一小节介绍了sqlite数据库的基本操作方法,本小节将详细介绍一个使用sqlite数据库的简单案例,以使读者可以更加快速地掌握sqlite数据库的使用方法,从而在开发中进行合理地使用。本案例运行效果分别如图2-10、图2-11和图2-12所示。

《OpenGL ES 3.x游戏开发(上卷)》一2.3 手机自带数据库——SQLite
《OpenGL ES 3.x游戏开发(上卷)》一2.3 手机自带数据库——SQLite

介绍完本案例的运行效果后,接下来将开发本案例中唯一的一个类——sample2_4_activity,其代码如下。

第9-43行为案例中的各个按钮添加监听器,监听器中调用对应的方法来实现数据库的打开/创建、关闭、插入、删除和查询等操作。

第43-60行为创建及打开数据库的方法,方法中首先获取了sqlitedatabase对象的引用,并为其指定数据库的存储路径和读写模式,然后用“create table”语句创建了一张名称为student的表。

第69-78行为向数据库中插入一条记录的方法,插入的记录内容为“'001','android',22,'283'”。

第79-87行为删除数据库中所有记录的方法。

第88-106行为从数据库中查找符合条件记录的方法,首先需要获取cursor对象的引用,并为其添加查找范围(具体范围为年龄大于20)。若查到相应记录,则将该记录信息用toast显示出来。

前一小节介绍了sqlite数据库中的一些操作,但有时数据库中的信息不但创建其的应用程序要使用,还希望能够分享给其他应用程序使用。这时就需要使用contentprovider组件了,contentprovider组件的基本情况如下所列。

android平台中每个应用程序都有自己的用户id并在自己的进程中运行,每个进程拥有独立的运行环境,这样可以保证程序的完整性。但这也使得应用程序在需要进行资源共享和数据通信时很不方便。为了解决这一问题,android提供了专门用来在应用程序之间分享数据的contentprovider组件。

contentprovider能将应用程序中特定的数据提供给其他应用程序使用,这些数据可以来自应用程序私有文件夹下的私有数据文件,也可以来自应用程序自己私有的sqlite数据库。当然,数据的来源还有很多其他选择,contentprovider组件本身并没有做出限制,读者可以充分发挥想象的空间。

使用contentprovider组件共享数据的基本方式是继承contentprovider类并重写其中的相应方法,具体情况在后面的案例中进行介绍。

别的应用程序想分享数据时需要使用contentresolver,通过contentresolver对象将需要分享数据的请求发送给contentprovider组件,而不能直接调用contentprovider组件。

下面使用contentprovider组件将上一小节的案例进行升级,使得此案例具有分享数据给其他应用程序的能力,其具体开发步骤如下。

(1)在案例sample2_4的com/bn/pp4包下创建mycontentprovider类,该类继承自contentprovider类,并要实现其中所有的抽象方法,具体代码如下。

第4-8行为声明uri匹配对象,并且设置匹配字符串。此匹配字符串在需要得到分享数据的应用程序中提供给contentresolver使用,以进行配对。

第11-13行重写了gettype方法,本案例中对gettype方法没有要求,因此其返回空值。

第15-24行重写了query方法,在匹配成功后,数据需求方通过contentresolver调用此方法查询需要的数据。

第26-32行重写了delete与insert方法,本案例中对这两个方法没有要求,因此都设置为返回空值。

第34-42行重写了oncreate方法,其功能为首先获取sqlitedatabase对象引用,然后创建或打开数据库,为信息的分享做好准备。

第44-47行重写了update方法,本案例中对这个方法没有要求,因此设置为返回空值。

(2)仅仅是完成上面的代码还是不够的,在android程序开发中,有一个很重要的配置文件androidmanifest.xml。要想使用contentprovider组件,在完成代码的开发后,还必须在该配置文件中进行相应的配置,将如下代码插入到androidmanifest.xml文件中的application标签中。

升级完了sample2_4使其具有了数据分享能力之后,就可以在别的应用程序中通过contentresolver匹配到sample2_4案例中的contentprovider组件获取分享的数据了。具体的开发步骤如下所列。

(1)创建项目sample2_4_from,将项目的包名设定为com.bn.pp4f,并创建一个继承自activity的类contentconsumeractivity,其代码如下。

第8-25行主要功能为获取contentresolver对象的引用,并给按钮添加监听器,使得按钮按下后可以通过contentresolver匹配到sample2_4案例中的contentprovider组件获取需要的数据。

第26-33行功能为将获取的sample2_4案例分享的数据显示到屏幕上的edittext控件中。

第35-38行为向edittext控件中添加文本信息的方法。

(2)sample2_4_from案例开发完成后,运行该案例,其效果如图2-13和图2-14所示。

《OpenGL ES 3.x游戏开发(上卷)》一2.3 手机自带数据库——SQLite
说明  图2-13为运行该案例后的界面效果图,图2-14为单击“获取”按钮后,通过contentresolver匹配到sample2_4案例中的contentprovider组件获取数据后的效果图。