Android数据存储技术分类
1.本地数据存取技术
- SharedPreferences(XML格式数据)
- File(二进制数据为主)
- SQLite(关系型数据)
2.远程数据存取技术
- 基于Socket使用TCP/IP直接访问网络服务器(数据从数据源直接传送到目的地)
- 基于HTTP相关协议访问Web服务(从互联网上获取HTML、json/xml、二进制格式的数据)
SharedPreferences
基本特点:
- 数据以“key-value”方式存储与处理
- 数据明文存储于xml文件中
- Android内置相应数据存取组件,使用简单方便
适用场景:
- 比较适合于保存少量的数据,更新不频繁,不需要进行复杂的查询,并且对安全性没有太大要求的场合。
使用文件保存数据
基本特点:
- 可以保存任意类型、任意大小的数据,但是需要自行编写数据解析代码
- Android使用标准Java编程方式,通过Stream(及派生或组合类型)存取底层文件
适用场景:
- 保存二 进制的,数据量 较大的 数据( 比如照片 、视频等 )
- 有特殊格式的文本型数据
- 有特殊处理需求的数据(比如数据需要加密后存储 )
使用关系数据库存储数据
基本情况:
- Android内置对SQLite的支持,在android.database.sqlite包中提供了相应的组件
- SQLite是一种单用户单文件型数据 库,文件保存于本机 内置存储空间,占用系统资源小,适合于 手机 这种 内存受限的运行环境
- 如果其它App需要访问这些数据,可以使用ContentProvider
适用场景:
- 以文本型数据为主
- 需要进行频繁的CRUD操作
手机、PC、智能设备之间数据直传
基本情况:
- Android应用中,可以使用java.net和android.net包中的类,基于TCP/IP协议(或其他网络协议)创建网络应用程序,完成数据存取任务
典型场景:
- 手机通过无线WiFi连入了局域网,需要 与PC通讯
- 各手机或相关智能设备之间短距离(比如通过 蓝牙,NFC,USB)直接交换数据
从互联网下载和上传数据
基本情况:
- Android内置HTTP组件,可以访问互 联网
- Android内置对Xml和Json格式数据的解析组件
- 有大量第三方组件可以访问互联网
应用场景:
- 一些互联网公司提供远程数据存取服务,它们向外界开放API(通常是RESTful服务),Android应用可以调用这些API,提取或保存数据。
SharedPreferences
- SharedPreferences是一种轻量级的数据存储方式,可以将键/值对的数据,保存在Android的文件系统中,完全屏蔽了文件系统的操作过程。
- 存储在应用程序的私有目录下(data/data/包名/shared_prefs)自己定义的xml文件中。
- SharedPreferences支持整形、布尔型、浮点型、长整形、字符串数据类型,特别适合用于保存少量数据,更新不频繁且安全性要求不高的场合,如:软件配置参数
存储数据步骤:
- 用SharedPreferences对象的方法edit()获得一个Editor对象。
- 通过putString以键值<String key,String value>方式把字符串值写入Editor对象中,其他类型数据调用相应的put< Type >()方法。
- 最后利用commit()或apply()方法提交数据。
private void savePrefs(String username){
SharedPreferences.Editor editor = getSharedPreferences("pref",Context.MODE_PRIVATE).edit();
editor.putString("username",username);
editor.apply();
获取SharedPreferences对象
-
可通过多种方式获得SharedPreferences对象。
-
Context.getSharedPreferences(String name, int mode)
name为文件名称。
mode为操作模式,默认的模式为0或MODE_PRIVATE,还可以用MODE_WORLD_READABLE 和MODE_WORLD_WRITEABLE。 -
Activity.getPreferences(int mode):只能在当前activity使用,一般不用
使用当前不带包名的类名作为文件的名称。
mode为操作模式,默认的模式为0或MODE_PRIVATE,还可以用MODE_WORLD_READABLE 和MODE_WORLD_WRITEABLE。 -
MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE两种模式已经在4.2版本废除
SharedPreferences数据读取
- 调用getSharedPreferences()函数
- 通过get< type >()函数获取保存在SharedPreferences中的键值对
private String readPrfs() {
SharedPreferences prefs = getSharedPreferences("pref",Context。MODE_PRIVATE);
return sp.getString("usermane","");
}
文件内部存取数据
private void saveData(String fileName, String username) {
//内部存储目录:data/data/包名/files/
try {
//1.打开文件输出流
FileOutputStream out = openFileOutput(fileName,MODE_PRIVATE);
//2.创建BufferedWriter对象
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
//3.写入数据
writer.write(username);
//4.关闭输出流
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private String readPrivateExStorage(String fileName) {
String data = null;
try {
//打开文件输出流
File file = new File(getExternalFilesDir(""), fileName);//path+fileName
FileInputStream in = new FileInputStream(file);
//创建BufferedWriter对象
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//读出数据
data = reader.readLine();
//关闭输入流
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
外部存储的私有文件存取
private String readPrivateExStorage(String fileName) {
String data = null;
try {
//打开文件输出流
File file = new File(getExternalFilesDir(""), fileName);//path+fileName
FileInputStream in = new FileInputStream(file);
//创建BufferedWriter对象
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//读出数据
data = reader.readLine();
//关闭输入流
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
外部存储的公有文件的存储
- 在AndroidManifest配置文件中设置权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- Android6.0及以上版本需申请运行时权限
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,"权限申请被拒绝", Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode){
case 1:
saveToSD("demo.jpg");
break;
}
}
数据库存取
SQLite数据库
- Android系统内置的数据库
- 一种轻量级关系型数据库
- 占用资源小,大概只需几百K内存,特别适合在嵌入式系统中使用
- 支持标准的SQL语法,支持事务机制
- Android专门提供了SQLiteOpenHelper类,对数据库进行操作
SQLite的数据类型
- NULL
- INTEGER:整数
- REAL:浮点数
- TEXT:文本与字符串
- BLOB:二进制类型的数据
直接访问数据库
- 在Activity中可以调用openOrCreateDatabase()方法创建或打开一个数据库,获取一个SQLiteDatabase对象的引用
- 创建的数据库存放的目录:/data/data/packageName/databases/
- 调用SQLiteDatabase类提供的相应方法将SQL命令直接发送给数据库
使用SQLiteOpenHelper
- 从SQLiteOpenHelper派生,提供一个构造函数,重写其onCreate()和onUpdate()方法
- 在Activity中调用getWritableDatabase()方法
MyDBHelper helper = new MyDBHelper (this);
SQLiteDatabase db = helper.getWritableDatabase();
ContentProvider
- ContentProvider是Android的四大组件之一
- 不同应用程序之间数据交换的标准API,实现数据在不同应用程序直接的共享
URI
- 统一资源标识符:uniform resource identifier
- ContentProvider以表的形式组织数据,使用的查询字符串有别于标准的SQL查询,增删改查等操作使用特殊的URI进行
自定义URI = content://com.carson.provider/User/1
content:// :主题名
com.carson.provider:授权信息
User:表明
1:记录(ID)
ContentResolver
- 作用:统一管理不同的ContentProvider间的操作
- 应用程序通过ContentResolver操作ContentProvider共享的数据
- getContentProvider():获取ContentResolver对象
- ContentProvider是单实例模式
管理联系人
- 调用getContentResolver()获取ContentResolver对象
- 调用insert()、update()、delete()、query()等方法
- 在AndroidMainfest配置文件声明许可
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
-
所需的Uri
管理联系人:ContactsContract.Contacts.CONTENT_URI
管理联系人的电话:ContactsContra.CommonDataKinds.phone.CONTENT_URI
管理联系人的Email:ContactsContra.CommonDataKinds.Email.CONTENT_URI -
注意:Android 6.0及以上版本需申请运行时权限
ContentProvider的工具类
Android提供了3个用于辅助ContentProvider的工具类:
-
ContentUris:操作URI,核心方法:
withAppendedId(uri, id):为uri路径加上ID部分
parseId(uri):解析uri中的ID -
UriMatcher,在ContentProvider中注册URI,根据URI匹配ContentProvider中对应的数据表
-
ContentObserver类:内容观察者,观察uri引起ContentProvider中的数据变化,并通知访问该数据的访问者
//ContentProvider相关的常量
private static final String CONTENT = "content://";
private static final String AUTHORIY = "com.example.sqlitedemo";
private static final String URI = CONTENT + AUTHORIY + "/" +TBL_NAME_STUDENT;
public static final Uri STUDENT_URI = Uri.parse(URI);
//ContentProvider返回的数据类型的定义、数据集合
//单项数据
private static final String STUDENT_TYPE_ITEM = "vnd.android.cursor.item/vnd." + AUTHORIY;
//数据集合
private static final String STUDENT_TYPE = "vnd.android.cursor.dir/vnd." + AUTHORIY;
static final int STUDENTS = 1;
static final int STUDENT_ITEM = 2;
static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
matcher.addURI(AUTHORIY,TBL_NAME_STUDENT,STUDENTS);
matcher.addURI(AUTHORIY,TBL_NAME_STUDENT + "/#",STUDENT_ITEM);
}