Android数据的四种存储方式
概述:四种数据存储方式:SharePreference、SQLite、Content Provider和File。Android系统中,数据基本都是私有的的,都是存放于“data/data/<包名>”目录下,所以要实现数据共享,正确方式是使用Content Provider。
一、SQLite
嵌入式设备 轻型数据库,存储位置在/data/data/<包名>/databases,只有五种数据类型:
NULL: 空值
INTEGER: 整数
REAL: 浮点数
TEXT: 字符串
BLOB: 大数据
BOOLEAN型可以用INTEGER的0和1代替true和false;
DATE类型则可以拥有特定格式的TEXT、REAL和INTEGER的值来代替显示,为了能方便的操作DATE类型,SQLite提供了一组函数。
创建数据库方式有两种:
原生SQLiteDatabase方式和SQLiteOpenHelper子类方式。
SQLiteOpenHelper
主要的三个方法:
1、onCreate()该方法是在你没有安装过(第一次运行)的时候执行,这时可以在这个函数中完成初始的数据表的创建
2、onUpgrade()该方法是在你安装过的情况下,对数据继续更新的时候执行,这时可以在这个函数完成数据库版本升级带来的旧版本的兼容问题,以及数据迁移问题。
3、onDowngrade()该方法是在现逆向降级(如应用由版本号4降级安装版本号为3的包)时必须重写的方法,如果应用降级覆盖安装时没有重写该方法则会崩溃。
onCreate()和onUpgrade()执行时机:
1、如果数据库文件不存在,SQLiteOpenHelper在自动创建数据库后会调用onCreate()方法,在该方法中一般需要创建表、视图等组件。在创建前数据库一般是空的,因此不需要先删除数据库中相关的组件。
2、如果数据库文件存在,并且当前版本号高于上次创建或升级的版本号,SQLiteOpenHelper会调用onUpgrade()方法,调用该方法后会更新数据库的版本号。在onUpgrade()方法中除了创建表、视图等组件外,还需要先删除这些相关的组件,因此,在调用onUpgrade()方法前,数据库是存在的,里面还原许多数据库组建。
二、SharedPreference
本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。存储位置在/data/data/<包名>/shared_prefs
SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。
存储数据步骤如下:
1、根据Context获取SharedPreferences对象
2、利用edit()方法获取Editor对象。
3、通过Editor对象存储key-value键值对数据。
4、通过commit()方法提交数据。
SharedPreference免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。
getSharedPreferences (String name, int mode),mode有四个选项:
1、Context.MODE_PRIVATE 只能被本应用程序读、写
2、Context.MODE_WORLD_READABLE 能被其他应用程序读,但不能写
3、Context.MODE_WORLD_WRITEABLE 能被其他应用程序读和写
4、Context.MODE_MULTI_PROCESS sdk2.3多个进程同时读写同一个SharedPreferences时它会检查文件是否修改
三、ContentProvider
在不同应用程序之间实现数据共享的一种机制。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个Content Provider都会对外提供一个公共的URI(包装成Uri对象),如果应用程序有数据需要共享时,就需要使用Content Provider为这些数据定义一个URI,然后其他的应用程序就通过Content Provider传入这个URI来对数据进行操作。此种方式忽略了底层的数据存储实现,ContentProvider提供了一种统一的通过Uri实现数据操作的方式。 其步骤为:
1、 在当前应用程序中定义一个ContentProvider
2、 在当前应用程序的AndroidManifest.xml中注册此ContentProvider
3、其他应用程序通过ContentResolver和Uri来获取此ContentProvider的数据
ContentResolver提供了诸如insert(), delete(), query()和update()之类的方法。用于实现对ContentProvider中数据的存取操作。
Uri是一个通用资源标志符,将其分为A,B,C,D 4个部分:
A:无法改变的标准前缀,包括;”content://”、”tel://”等。当前缀是”content://”时,说明通过一个Content Provider控制这些数据
B:URI的标识,它通过authorities属性声明,用于定义了是哪个ContentProvider提供这些数据。为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。例如;”content://com.test.data.myprovider”
C:路径,可以近似的理解为需要操作的数据库中表的名字,如:”content://hx.android.text.myprovider/name”中的name
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;
四、File
即常说的文件(I/O)存储方法,常用语存储大数量的数据,但是缺点是更新数据将是一件困难的事情。默认情况下,文件是应用程序私有的,其他应用不能访问。当用户卸载应用程序时这些文件也跟着被删除。存储位置在/data/data/<包名>/files
创建和写入一个内部存储的私有文件:
1、调用Context的openFileOutput()函数,填入文件名和操作模式,它会返回一个FileOutputStream对象。
2、通过FileOutputStream对象的write()函数写入数据。
3、FileOutputStream对象的close ()函数关闭流。
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
openFileOutput(String name, int mode)
name参数: 用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。
mode参数:用于指定操作模式,分为四种:
Context.MODE_PRIVATE = 0
为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。
Context.MODE_APPEND = 32768
该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE = 1
表示当前文件可以被其他应用读取。
MODE_WORLD_WRITEABLE
表示当前文件可以被其他应用写入。
读取一个内部存储的私有文件:
1、调用openFileInput( ),参数中填入文件名,会返回一个FileInputStream对象。
2、使用流对象的 read()方法读取字节
3、调用流的close()方法关闭流
应用编译时保存静态文件
应该把文件保存在项目的 res/raw/ 目录下,你可以通过 openRawResource()方法去打开它(传入参数R.raw.filename),这个方法返回一个 InputStream流对象你可以读取文件但是不能修改原始文件。
InputStream is = this.getResources().openRawResource(R.raw.filename);
保存内存缓存文件
有时候我们只想缓存一些数据而不是持久化保存,可以使用getCacheDir()去打开一个文件,文件的存储目录( /data/data/包名/cache )是一个应用专门来保存临时缓存文件的内存目录。
使用外部存储(sdcard)
添加外部存储访问限权
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
检测外部存储的可用性
//获取外存储的状态
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// 可读可写
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// 可读
} else {
// 可能有很多其他的状态,但是我们只需要知道,不能读也不能写
}
访问外部存储器中的文件
1、如果 API 版本大于或等于8,使用getExternalFilesDir (String type)
该方法打开一个外存储目录,此方法需要一个类型,指定你想要的子目录,如类型参数DIRECTORY_MUSIC和 DIRECTORY_RINGTONES(传null就是你应用程序的文件目录的根目录)。通过指定目录的类型,确保Android的媒体扫描仪将扫描分类系统中的文件(例如,铃声被确定为铃声)。如果用户卸载应用程序,这个目录及其所有内容将被删除。
例如:File file = new File(getExternalFilesDir(null), “fanrunqi.jpg”);
2、如果API 版本小于 8 (7或者更低),使用getExternalStorageDirectory ()
转载:> http://blog.sina.com.cn/s/blog_4d661a8c010138v7.html
推荐阅读
-
Android listview数据显示及提示信息的实例
-
详解Android的MVVM框架 - 数据绑定
-
Android编程实现手机自带内部存储路径的获取方法
-
android编程实现sd卡读取数据库的方法
-
Android开发中Listview动态加载数据的方法示例
-
Android三种网络通讯方式及Android的网络通讯机制
-
Android数据共享 sharedPreferences 的使用方法
-
Android onClick按钮单击事件的四种常用写法
-
vue的style绑定background-image的方式和其他变量数据的区别详解
-
t-sql清空表数据的两种方式示例(truncate and delete)