1、 数据存储与访问016.1 SharedPreference 存储0203046.2 SQLite 数据库6.3 文件存储6.4 数据共享056.5 本章小结本章导读任何一个应用程序都少不了与数据进行交互,例如任何一个应用程序都少不了与数据进行交互,例如QQ、微信、手、微信、手机银行等都需要大量的数据。通常情况下,将这些数据存放在机银行等都需要大量的数据。通常情况下,将这些数据存放在远程远程服务器的数据库服务器的数据库中,通过接口进行读取。中,通过接口进行读取。但是对于少量的数据,如程序配置信息(是否推送等),如果也采但是对于少量的数据,如程序配置信息(是否推送等),如果也采用存放远程数据库的
2、方法,则运行效率低,还占用数据库资源用存放远程数据库的方法,则运行效率低,还占用数据库资源,对,对于这种情况,于这种情况,Android提供了三种解决办法:使用提供了三种解决办法:使用SharedPreferences 存储数据、存储数据、Android内置轻量级数据库内置轻量级数据库 SQLite 存储数据、借助存储数据、借助 Java 的的 I/O 体系体系实现文件存储。实现文件存储。本章导读本章主要内容有:本章主要内容有:(1)SharedPreferences 存储;存储;(2)SQLite 数据库使用(包括手动建库和代码建库);数据库使用(包括手动建库和代码建库);(3)文件存储文件
3、存储(包括内部存储和外部存储);(包括内部存储和外部存储);(4)Android 外部存储的公有存储空间和私有存储空间外部存储的公有存储空间和私有存储空间;(5)ContentProvider 的使用(包括创建数据提供者和使的使用(包括创建数据提供者和使用数据提供者)。用数据提供者)。016.1 SharedPreference 存储SharedPreferences 数据文件的存储路径是唯一的,以数据文件的存储路径是唯一的,以 XML 文件的形式文件的形式保存于保存于/data/data/shared_prefs 目录下。目录下。将数据存储到将数据存储到SharedPreferences的基
4、本步骤如下:的基本步骤如下:(1)调用)调用 Context 提供的提供的 getSharedPreferences()方法来获取方法来获取 SharedPreferences 实例实例 SharedPreferences mySharedPreferences=getSharedPreferences(book_info,MODE_PRIVATE);6.1.1 将数据存储到 SharedPreferences016.1 SharedPreference 存储getSharedPreferences(String name,int mode)方法涉及两个参数,第一方法涉及两个参数,第一个参数个
5、参数 name 表示要访问的文件,由于表示要访问的文件,由于 SharedPreferences 文件存储的路文件存储的路径是唯一的,因此,此处径是唯一的,因此,此处 name 只需描述文件名即可。只需描述文件名即可。若为写入操作,而系统并没有若为写入操作,而系统并没有 name 文件,则会自动创建一个名为文件,则会自动创建一个名为 name 的文件。第二个参数的文件。第二个参数 mode 表示操作模式,例如表示操作模式,例如 MODE_PRIVATE,表,表示可以被本应用程序读示可以被本应用程序读/写。写。6.1.1 将数据存储到 SharedPreferences016.1 SharedP
6、reference 存储(2)获得)获得 Editor 对象来实现对数据的写入对象来实现对数据的写入SharedPreferences 本身并不具备写入数据的能力,它是通过调用自身的本身并不具备写入数据的能力,它是通过调用自身的 edit()方法来获取对应的方法来获取对应的 Editor 对象,由对象,由 Editor 对象来实现对数据的写对象来实现对数据的写入。例如:入。例如:Editor editor=mySharedPreferences.edit();editor.putString(bookname,Android应用开发实践教程应用开发实践教程);(3)调用)调用 apply()或
7、或 editor()方法提交修改方法提交修改6.1.1 将数据存储到 SharedPreferences016.1 SharedPreference 存储 apply()是将修改数据原子提交到内存是将修改数据原子提交到内存,而后异步真正提交到硬件磁盘而后异步真正提交到硬件磁盘,而而 commit()是同步地提交到硬件磁盘。是同步地提交到硬件磁盘。apply()方法会覆写之前内存中方法会覆写之前内存中的值,异步写入磁盘的值只是最后的值,而的值,异步写入磁盘的值只是最后的值,而 commit 每次都要写入磁盘,每次都要写入磁盘,而磁盘的写入相对来说是很低效的,所以而磁盘的写入相对来说是很低效的,所
8、以 apply 方法在频繁调用时要比方法在频繁调用时要比 commit 效率高很多。效率高很多。apply()方法没有返回值,而方法没有返回值,而 commit()方法返回方法返回 boolean 类型的值,类型的值,表明提交修改是否成功。而且表明提交修改是否成功。而且 apply()方法不会有任何失败的提示。方法不会有任何失败的提示。apply()和和 commit()这两方法的区别在于这两方法的区别在于:016.1 SharedPreference 存储SharedPreferences 接口至少提供了以下的方法来读取应用程序的数据。接口至少提供了以下的方法来读取应用程序的数据。publi
9、c abstract String getString(String key,String defValue):获取:获取 key 所指向的所指向的 value 值。若该值。若该 key 不存在,不存在,则返回默认值则返回默认值 defValue。public abstract Map getAll():获取所有:获取所有 SharedPreferences 数据,该函数返回值是一个以数据,该函数返回值是一个以 Key-Value 形式描述的形式描述的 Map 对象。对象。public abstract boolean contains(String key):判断是否包含:判断是否包含 ke
10、y 指向的指向的数据。数据。6.1.2 从 SharedPreferences 中读取数据016.1 SharedPreference 存储6.1.2 从 SharedPreferences 中读取数据String bookName=mySharedPreferences.GetString(bookname,none);/读取 key 值为bookname 指向的数据,若无,则返回none例如以下代码:例如以下代码:016.1 SharedPreference 存储6.1.3 SharedPreferences 举例026.2 SQLite 数据库l SQLite 是一个 2000 年由 D
11、.Richard Hipp 发布的开源嵌入式关系数据库l 普通数据库的管理系统比较庞大和复杂,会占用了较多的系统资源l 轻量级数据库 SQLite 的特点:(1)适合用于嵌入式系统(2)占用资源少,运行高效可靠,可移植性强026.2 SQLite 数据库SQLite 的核心大约有 3 万行标准 C 代码,因为模块化的设计使这些代码非常易于理解模块将复杂的查询过程分解为细小的工作进行处理SQLite 数据库由 8 个独立的模块构成,这些独立模块又构成了三个主要的子系统026.2 SQLite 数据库026.2 SQLite 数据库虚拟机:SQLite 数据库体系结构中最核心的部分是虚拟机,也称为
12、虚拟数据库引擎(Virtual Database Engine,VDBE)。与 Java 虚拟机相似,虚拟数据库引擎用来解释并执行字节代码。虚拟数据库引擎的字节代码由128个操作码构成,这些操作码主要用以对数据库进行操作,每一条指令都可以完成特定的数据库操作,或以特定的方式处理栈的内容。接口:由 SQLite C API 组成,因此无论是应用程序、脚本,还是库文件,最终都是通过接口与 SQLite 交互。026.2 SQLite 数据库编译器:在编译器中,分词器和分析器对SQL语句进行语法检查,然后把 SQL 语句转化为便于底层处理的分层数据结构,这种分层的数据结构称为“语法树”。然后把语法树
13、传给代码生成器进行处理,生成一种用于 SQLite 的汇编代码,最后由虚拟机执行。后端:后端由B-树、页缓存和操作系统接口构成,B-树和页缓存共同对数据进行管理。B-树的主要功能就是索引,它维护着各个页面之间复杂的关系,便于快速找到所需数据。页缓存的主要作用是通过操作系统接口在B-树和磁盘之间传递页面。026.2 SQLite 数据库6.2.1 手动建库在 Android 系统中,每个应用程序的 SQLite 数据库被保存在各自的/data/data/databases 目录下。缺省情况下,所有数据库都是私有的,仅允许创建数据库的应用程序访问,如果需要共享数据库则可以使用 ContentPro
14、vider虽然应用程序完全可以在代码中动态建立 SQLite 数据库,但使用命令行手工建立和管理数据库仍然是非常重要的内容,对于调试使用数据库的应用程序非常有用。026.2 SQLite 数据库6.2.1 手动建库手动建立数据库指的是使用 sqlite3 工具,通过手工输入命令行完成数据库的建立过程。Sqlite3 是 SQLite 数据库自带的一个基于命令行的 SQL命令 执行工具,并可以显示命令执行结果。Android SDK 的 tools 目录有 sqlite3 工具,同时,该工具也被集成在Android系统中。下面的内容将介绍如何连接到模拟器中的 Linux 系统,并在 Linux
15、系统中启动 sqlite3 工具,在 Android 程序目录中建立数据库和数据表,并使用命令在数据表中添加、修改和删除数据。026.2 SQLite 数据库6.2.1 手动建库使用 adb shell 命令连接到模拟器的 Linux 系统,在 Linux 命令提示符下输入 sqlite3 可启动 sqlite3 工具启动 sqlite3 后会显示 SQLite 的版本信息,显示内容如下:026.2 SQLite 数据库6.2.1 手动建库启动 sqlite3 后会显示 SQLite 的版本信息,显示内容如下:026.2 SQLite 数据库6.2.1 手动建库在启动 sqlite3 工具后,
16、提示符从“#”变为“sqlite”,表示用户进入 SQLite 数据库交互模式,此时可以输入命令建立、删除或修改数据库的内容。正确退出sqlite3工具的方法是使用.exit命令026.2 SQLite 数据库6.2.1 手动建库026.2 SQLite 数据库6.2.1 手动建库026.2 SQLite 数据库6.2.1 手动建库原则上,每个应用程序的数据库都保存在各自的/data/data/databases 目录下。但如果使用手工方式建立数据库,则必须手工建立数据库目录,目前版本无需修改数据库目录的权限。026.2 SQLite 数据库6.2.1 手动建库在SQLite数据库中,每个数据
17、库保存在一个独立的文件中。使用“sqlite3+文件名”的方式打开数据库文件,如果指定的文件不存在,sqlite3工具则自动创建新文件下面的代码将创建名为 employee 的数据库,在文件系统中将产生一个名为 employee.db 的数据库文件026.2 SQLite 数据库6.2.1 手动建库下面的代码在数据库中,构造了一个名为 employee 的表。使用 create table 命令,关系模式为 employee(_id,name,age,height)表包含四个属性,_id 是整型的主键;name 表示姓名,字符型,not null 表示属性值一定要填写,不可以为空值;age 表
18、示年龄,整数型;height 表示身高,浮点型。026.2 SQLite 数据库6.2.1 手动建库026.2 SQLite 数据库6.2.1 手动建库也可以使用.schema 命令查看建立表时使用的 SQL 命令如果当前数据库中包含多个表,则可以使用.schema 表名的形式,显示指定表的建立命令026.2 SQLite 数据库6.2.1 手动建库下一步是向 employee 表中添加数据,使用 insert into values 命令在下面的代码成功运行后,数据库的 employee 表将有三条数据。026.2 SQLite 数据库6.2.1 手动建库下一步是向 employee 表中添
19、加数据,使用 insert into values 命令在下面的代码成功运行后,数据库的 employee 表将有三条数据。026.2 SQLite 数据库6.2.1 手动建库上面的查询结果看起来不是很直观,使用表格方式显示更应更符合习惯,因此可以使用.mode 命令更改结果输出格式.mode 命令除了支持常见的 column 格式外,还支持csv格式、html格式、insert格式、line格式、list格式、tabs 格式和 tcl 格式下面使用 column 格式显示 employee 数据表中的数据信息026.2 SQLite 数据库6.2.1 手动建库更新数据可以使用 update
20、命令,命令格式为update 表名 set 属性=”新值”where 条件更新数据后,同样使用select命令显示数据,确定数据是否正确更新下面的代码将 LiBai 的年龄更新为112026.2 SQLite 数据库6.2.1 手动建库删除数据可以使用 delete 命令命令格式为delete from 表名where 条件下面的代码将 _id 为 3 数据从表 employee 中删除026.2 SQLite 数据库6.2.1 手动建库Sqlite3 工具还支持很多命令,可以使用.help 命令查询 sqlite3 的命令列表,也可以参考下表026.2 SQLite 数据库编号编号命令命令说
21、明说明1 1.bail ON|OFF.bail ON|OFF遇到错误时停止,缺省为遇到错误时停止,缺省为 OFFOFF2 2.databases.databases显示数据库名称和文件位置显示数据库名称和文件位置3 3.dump?TABLE?.dump?TABLE?.将数据库以将数据库以SQLSQL文本形式导出文本形式导出4 4.echo ON|OFF.echo ON|OFF开启和关闭回显开启和关闭回显5 5.exit.exit退出退出6 6.explain ON|OFF.explain ON|OFF开启或关闭适当输出模式,如果开启模式将开启或关闭适当输出模式,如果开启模式将更改为更改为col
22、umncolumn,并自动设置宽度,并自动设置宽度7 7.header(s)ON|OFF.header(s)ON|OFF开启或关闭标题显示开启或关闭标题显示8 8.help.help显示帮助信息显示帮助信息9 9.import FILE TABLE.import FILE TABLE将数据从文件导入表将数据从文件导入表1010.indices TABLE.indices TABLE显示表中所的列名显示表中所的列名1111.load FILE?ENTRY?.load FILE?ENTRY?导入扩展库导入扩展库手动建库026.2 SQLite 数据库手动建库026.2 SQLite 数据库手动建库
23、026.2 SQLite 数据库6.2.2 SQLiteDatabase在 android.database.sqlite 包中,Android 提供了 SQLiteDatabase 类,该类封装了一些操作数据库的 API,使用该类可以完成对数据库中的数据添加、查询、更新和删除的操作。由于在 Context 类中定义了 openOrCreateDatabase()方法,我们可以在活动页面代码或任何能取到 Context 的地方获取 SQLiteDatabase 实例。026.2 SQLite 数据库6.2.3 SQLiteOpenHelperSQLiteOpenHelper 是 Android
24、 提供的一个管理数据库的工具类,用于帮助创建或者打开和管理一个 SQLite 数据库。通常的用法是创建 SQLiteOpenHelper 的子类,IDE 会提示重写它的 onCreate()和 onUpgrade()两个方法。026.2 SQLite 数据库6.2.3 SQLiteOpenHelper(1)onCreate(SQLiteDatabase db):当调用SQLiteOpenHelper的getWritableDatabase()或getReadableDatabase()方法获取SQLiteDatabase实例时,如果数据库不存在,系统会自动生成一个数据库,然后调用onCreat
25、e()方法。onCreate()方法在初次生成数据库时才会被调用,通常会在这里去处理一些创建表的逻辑。026.2 SQLite 数据库6.2.3 SQLiteOpenHelper(2)onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion):用于升级软件时更新数据库的表结构。只要某次创建 SQLiteOpenHelper 时指定的数据库版本号高于之前指定的版本号,系统就会自动触发 onUpgrade()方法。026.2 SQLite 数据库6.2.3 SQLiteOpenHelper026.2 SQLite 数据库6.2.3 SQLi
26、teOpenHelperSQLiteOpenHelper 提供 getReadableDatabase()和getWritableDatabase()两个方法,都可以打开(或创建)SQLite 数据库(如果数据库存在则直接打开,否则创建一个新的数据库),并返回一个可进行读写操作的 SQLite 数据库对象。通常情况下两种方法的实现效果是一样的。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法将返回一个“只能进行读操作不能进行写操作”的 SQLite数据库对象,而 getWritableDatabase()方法将出现异常。026.2 SQLite
27、 数据库6.2.4 Cursor 和 ContentValue026.2 SQLite 数据库6.2.4 Cursor 和 ContentValue026.2 SQLite 数据库6.2.5 代码建库026.2 SQLite 数据库6.2.5 代码建库036.3 文件存储手机的存储空间一般分为两块,一块用于内部存储,另一块用于外部存储(SD卡)。早期的SD卡是可插拔式的存储芯片,后来越来越多的手机把 SD 卡固化到了手机内部,Android 仍然称之为外部存储。内存(Memory/RAM)是一种临时的数据存储器,当断电后数据就会消失,并且读取和写入的速度非常快。通常我们所说的手机的运行内存就是
28、它。内部存储(Internal Storage)不同于内存(Memory/RAM),它们是两个东西(two things)。036.3 文件存储在原先的时候内部存储和外部存储是分开的,这种情况多发生 Android 4.4 及以前,比较好理解。但是随着 Android 手机的发展,渐渐的都做成了一体机甚至将内部存储和外部存储都集成在了一起,只是在逻辑上区分了内部存储和外部存储。甚至到了现在很多厂商连外置 SD 卡的卡槽都不提供了。036.3 文件存储内存内存内部存储内部存储internal外部存储外部存储externalAndroid 4.4以下系统机身存储(内置存储)外置SD卡Android
29、 4.4 以下以下系统的内部存储和外部存储系统的内部存储和外部存储036.3 文件存储内部存储内部存储internal外部存储外部存储externalAndroid 4.4及以上系统机身存储(内置存储)外置SD卡外部存储外部存储external内存内存Android 4.4 及以上系统及以上系统的内部存储和外部存储的内部存储和外部存储036.3 文件存储6.3.1 内部存储注意:内部存储(Internal Storage)不是内存(Memory/RAM),它是手机中的一块存储区域,是系统本身和系统应用程序主要的数据存储所在地。手机的内部存储通常不会很大,一旦手机的内部存储容量被用完,可能会出现
30、手机无法使用的情形。对于开发者来说,不宜存储视频等大文件,适合存储一些小文件。比如我们常常用的 SharedPreferences 和 SQLite 数据库都是存储在内部存储中的,不会占用太大的空间。036.3 文件存储6.3.1 内部存储Android系统提供了如下的API。Environment.getDataDirectory().getAbsolutePath();/获取手机内部存储空间的绝对路径 getFilesDir().getAbsolutePath();/获取当前应用包名文件夹下的files文件夹 getCacheDir().getAbsolutePath();/获取当前应用包
31、名文件夹下cache文件夹 getDir(String name,MODE_PRIVATE);/在内部存储空间内创建(或打开现有的)目录036.3 文件存储6.3.1 内部存储内部存储位于系统中很特殊的一个位置,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们
32、要尽量避免使用。036.3 文件存储6.3.1 内部存储Shared Preferences 和 SQLite 数据库都是存储在内部存储空间上的。内部存储一般用 Context 来获取和操作。Context 提供了如下两个方法来打开应用程序的数据文件夹里的文件 IO 流。(1)public abstract FileInputStream openFileInput(String name):(2)public abstract FileOutputStream openFileOutput(String name,int mode):036.3 文件存储6.3.2 外部存储(读写SD卡上的文
33、件)当程序通过 Context 的 openFileInput()和openFileOutput()来打开文件输入流、输出流时,程序所打开的都是应用程序的数据文件夹里的文件,这样所存储的文件大小可能比较有限。通常情况下,手机自身的存储空间会有一定的容量限制,一味地将文件存储在手机存储器上可能会出现空间不够或者空间不足引发的应用程序运行效率的问题,因此为了更好地利用存储器有限的空间,可以考虑将一部分大数据文件存放于外部存储。036.3 文件存储6.3.2 外部存储(读写SD卡上的文件)Android 把外部存储分成了两块区域:公有存储空间和私有存储空间。Android 从 7.0 开始加强了 S
34、D 卡的权限管理,即使 App 声明了完整的 SD 卡操作权限,系统仍然默认禁止该 App 访问外部存储;不过系统默认关闭存储只是关闭外部存储的公共空间,外部存储的私有空间依然可以正常读写。如果要在外部存储的公有存储空间读写文件,还需要请求“动态获取读写 SD 卡”的权限,只有当用户授权读写 SD 卡时才执行读写。046.4 数据共享6.4.1 ContentProvider通常 Android 应用程序之间的数据不能够直接访问,为了实现不同应用程序之间的数据交互,Android 提供了一个接口 ContentProvider,它是不同应用程序之间进行数据交互的标准 API,一个应用程序把自己
35、的数据通过 ContentProvider 暴露给其他应用程序,而其他程序通过 ContentResolver来获取暴露的数据,如图所示。046.4 数据共享6.4.1 ContentProvider应用程序之间交互的数据可以是数据库中的数据,也可以是文件系统中的数据,还可以是网络数据,提供者实现 ContentProvider 类中对数据操作的接口函数,而调用者使用 ContentResolver 对象通过 URI 间接调用 ContentProvider。046.4 数据共享6.4.1 ContentProviderContentProvider 在程序的操作中所提供的是一个操作的标准,所
36、以用户如果要想依靠此标准进行数据操作的时候,必须使用到android.content.ContentResolver 类完成,而这个类中所给出的操作方法与 ContentProvider 是一一对应的,当用户调用了 ContentResolver 类的方法时实际上就相当于调用了 ContentProvider 类中的对应方法。046.4 数据共享6.4.1 ContentProviderContentProvider 为 App 存取内部数据提供统一的外部接口,让不同的应用之间得以共享数据。ContentProvider 操作的是本设备其他应用的内部数据,是一种中间层次的数据存储形式。Cont
37、entProvider 作为中间接口,本身并不直接保存数据,而是通过 SQLiteOpenHelper 与 SQLiteDatabase 间接操作底层的 SQLite。所以要想使用 ContentProvider,首先得实现 SQLite 的数据库帮助类,然后由 ContentProvider 封装对外的接口。046.4 数据共享6.4.2 Uri Uri 作为提供者跟调用者交互的重要桥梁,可以分为四个组成部分,语法结构如下所示:content:/Uri 各组成部分的解释如下。content:/:通用前缀,表示该 Uri 用于 ContentProvider 定位资源,类似于网址前缀 http
38、:/。:用于唯一标识一个ContentProvider,外部调用者可以根据此标识访问该ContentProvider。通常可将 authority 设置为包名和类名的全称,以保证唯一性046.4 数据共享6.4.2 Uri:资源部分,可用来表示待操作的数据集。:数据编号,用来唯一确定数据集中的一条记录,用来匹配数据集中 _ID 字段的值。这个部分是可以省略的。通常对于利用字符串来定义 Uri,如“content:/com.mialab.contentprovider/data”,为了将字符串转化为 Uri,可以调用 Uri 工具类的 parse()方法进行转换,如:Uri uri=Uri.pa
39、rse(content:/com.mialab.contentprovider/data);046.4 数据共享6.4.2 Uri046.4 数据共享6.4.3 UriMatcher 和 ContentUris1UriMatcher为了确定该 ContentProvider 实际能处理的Uri,以及确定每个方法中 Uri 参数所操作的数据,Android 系统提供了 UriMatcher 工具类。UriMatcher 工具类提供两个方法:(1)void addUri(String authority,String path,int code):用于向 UriMatcher 对象注册 Uri。其
40、中 authority 和 path 组成一个 Uri,而 code 代表该Uri对应的匹配码。(2)int match(Uri uri):注册 Uri 与传入的 Uri 匹配,如果匹配成功,则返回相应的 code(匹配码);如果匹配失败,则返回-1。046.4 数据共享6.4.3 UriMatcher 和 ContentUris1UriMatcher首先注册所有的需要匹配的 Uri 路径。UriMatcher uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(com.mialab.provider.content
41、provider,data_table,1);uriMatcher.addURI(com.mialab.provider.contentprovider,data_table/#,2);常量 UriMatcher.NO_MATCH 表示不匹配任何路径的返回码(-1)。046.4 数据共享6.4.3 UriMatcher 和 ContentUris1UriMatcher注册完需要匹配的 Uri 后,就可以使用 uriMatcher.match(uri)方法对输入的 Uri 进行匹配,如果匹配成功则返回匹配码。如果 match()方法匹配 content:/com.mialab.provider.
42、contentprovider/data_table 路径,返回匹配码为 1。“#”号为通配符,如果 match()方法匹配content:/com.mialab.provider.contentprovider/data_table/8 路径,返回匹配码为 2。046.4 数据共享6.4.3 UriMatcher 和 ContentUris2ContentUris除此以外,Android 还提供一个 ContentUris 工具类,用于操作 Uri 字符串的工具类,它提供如下两个方法:(1)static Uri withAppendedId(Uri uri,long id):用于为路径加上
43、ID 部分。如:Uri uri=Uri.parse(content:/com.mialab.contentprovider/data);Uri newUri=ContentUris.withAppendedId(uri,1);此时 newUri 为:content:/com.mialab.contentprovider/data/1046.4 数据共享6.4.3 UriMatcher 和 ContentUris2ContentUris(2)static long parseId(Uri uri):用于从指定的Uri中解析出所包含的ID值。Uri uri=Uri.parse(content:/c
44、om.mialab.provider.contentprovider/data/1);long dataId=ContentUris.parseId(uri);/dataId 值为1046.4 数据共享6.4.4 ContentResolverContentResolver 提供的方法与 ContentProvider 是一一对应的,比如query、insert、update、delete、getType 等方法,连方法的参数类型都一模一样。要获取 ContentResolver 对象,可以使用Context提供的getContentResolver()方法。例如以下的示例代码:Content
45、Resolver cr=getContentResolver();046.4 数据共享6.4.4 ContentResolver046.4 数据共享6.4.5 创建数据提供者通过继承 ContentProvider 类创建一个数据提供者,创建步骤可分为三步:(1)创建一个继承 ContentProvider 的 Java 类,重载类中的 6 个函数:onCreate()、insert()、delete()、update()、qurey()、getType()。(2)声明 CONTENT_URI,实现 UriMatcher。(3)注册 ContentProvider。应用程序必须在配置文件And
46、roidManifest.xml 中注册 Contentrovider 方可使用。046.4 数据共享6.4.5 创建数据提供者注册 ContentProvider 只需在 元素下添加 子元素即可,代码如下:name 属性值指定 ContentProvider 的实现类的类名,authorities 指定ContentProvider 对应的 Uri,android:exported 指定该 ContentProvider 是否允许其他应用调用。046.4 数据共享6.4.5 使用数据提供者当一个程序通过 ContentProvider 暴露数据之后,其他应用程序即可通过 ContentRes
47、olver 对象共享这些数据。ContentResolver 是通过 Uri 来查询ContentProvider 中提供的数据。程序开发者只需知道 Uri 和数据集的数据格式,即可对数据进行操作。获取共享数据的操作步骤如下:(1)获取 ContentResolver 对象 调用 getContentResolver()方法获取 ContentResolver 对象。ContentResolver resolver=getContentResolver();046.4 数据共享6.4.5 使用数据提供者(2)操作数据与 ContentProvider 类中数据操作(增删改查)方法对应,Cont
48、entResolver 对象也有四个方法,分别为 insert()、delete()、update()和query(),这四个方法的参数列表与 ContentProvider 中对应的方法一致。调用任意一个方法即可触发 Uri 对应的 ContentProvider 中的方法。例如:Uri uri=Uri.parse(content:/com.mialab.contentprovider/data);String selection=id=1;int result=resolver.delete(uri,selection,null);/删除data中id为1的数据本章小结本章主要介绍了如何对
49、于轻量级数据实现存储与访问。本章主要介绍了如何对于轻量级数据实现存储与访问。根据根据数据量的规模以及使用需求,介绍了三种存储方式:使用数据量的规模以及使用需求,介绍了三种存储方式:使用SharedPreferences、使用文件以及、使用文件以及使用使用 SQLite 数据库数据库。SharedPreferences 是是一种一种轻量级轻量级 xml 文档文档,可以用于存储少,可以用于存储少量的数据,应用程序可以读取自身量的数据,应用程序可以读取自身的的 SharedPreferences 文件。文件。本章小结借助于借助于 Java 的的 I/O 体系体系,应用程序可以读写系统中的文件,应用程序可以读写系统中的文件,也可以读写外部存储器中的文件。也可以读写外部存储器中的文件。SQLite 数据库是数据库是 Android 内置内置的数据库,用户可以的数据库,用户可以通过通过 SQLiteDataBase 访问访问 SQLite 数据库数据库,对数据进行增删改查。考虑到有些应用需要访问其,对数据进行增删改查。考虑到有些应用需要访问其他应用程序的数据,本章还介绍了他应用程序的数据,本章还介绍了利用利用 ContentProvider 和和 ContentResolver 实现实现数据共享。数据共享。