您的位置:首页 > 移动开发 > Android开发

Android数据存储与持久化

2016-09-29 23:00 330 查看

一、持久化技术简介

瞬时数据是指那些存储在内存当中,有可能会因为程序关闭或其他原因导致内存被回收而丢失的数据。这对于一些关键性的数据信息来说是绝对不能容忍的,谁都不希望自己刚发出去的一条微博,刷新一下就没了吧。那么怎样才能保证让一些关键性的数据不会丢失呢?这就需要用到数据持久化技术了

数据持久化就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失。保存在内存中的数据是处于瞬时状态的,而保存在存储设备中的数据是处于持久状态的,持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换

持久化技术被广泛应用于各种程序设计的领域当中,而本书中要探讨的自然是Android中的数据持久化技术。Android 系统中主要提供了三种方式用于简单地实现数据持久化功能,即文件存储、SharedPreference 存储以及数据库存储。当然,除了这三种方式之外,你还可以将数据保存在手机的SD 卡中,不过使用文件、SharedPreference 或数据库来保存数据会相对更简单一些,而且比起将数据保存在SD 卡中会更加的安全

以上引用自郭霖的《第一行代码》

二、SharedPreferences

使用键值对的方式来存储数据,SharedPreferences 文件都是存放在/data/data/<packagename>/shared_prefs/目录下的

获取SharedPreferences 对象的三种方法

1、Context 类中的getSharedPreferences()方法

2、Activity 类中的getPreferences()方法

3、PreferenceManager 类中的getDefaultSharedPreferences()方法

写数据到SharedPreferences 中

为了把数据写入SharedPreferences文件,需要通过执行edit()创建一个 SharedPreferences.Editor,然后通过Editor对象的putXxx()方法存入键值对数据,最后commit()方法提交数据

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score), newHighScore);
editor.commit();


从SharedPreferences 中读取数据

public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";

@Override
protected void onCreate(Bundle state){
super.onCreate(state);
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}

@Override
protected void onStop(){
super.onStop();

// We need an Editor object to make preference changes
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);

// Commit the edits!
editor.commit();
}
}


三、手机内存

保存在手机内存的数据是应用私有的,别的应用没有权限访问,当用户卸载应用的时候,数据也会随之被删除

通过Activity的openFileOutput()和 openFileInput()方法可以拿到输出流和输入流,然后通过流读写数据

1、创建并写入文件到手机内存

String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();


openFileOutput(),参数1:文件名,参数2:文件访问模式,文件默认存储到/data/data/<packagename>/files/ 目录下的

模式说明
MODE_PRIVATE私有模式,默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容
MODE_WORLD_READABLE只读模式,API 17后过时
MODE_WORLD_WRITEABLE只写模式,API 17后过时
MODE_APPEND追加模式,如果该文件已存在就往文件里面追加内容,不存在就创建新文件
 

Android 7.0 之后,使用 FileProvider分享私有数据

2、从手机内存读取文件

FileInputStream inputStream = null;
try {
inputStream = openFileInput(FILENAME);
...
} catch (Exception e) {
e.printStackTrace();
}finally {
if (inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


3、缓存文件

方法说明
getCacheDir获取缓存路径
getFilesDir()获取缓存的绝对路径

File.createTempFile()

public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
catch (IOException e) {
// Error while creating file
}
return file;
}


四、手机外部存储

读写文件权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}

/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}


将文件以public形式保存在外部存储

public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}


将文件以private形式保存在外部存储中

public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}


查询剩余空间

可以通过File类的getFreeSpace()方法获取剩余空间,getTotalSpace()方法获取总大小

五、删除文件

可以通过File对象的delete()方法删除文件,如果文件保存在内部存储,可以通过Context的deleteFile(fileName)方法删除

六、Environment

1、getExternalStorageState():获取外部存储状态

状态说明
MEDIA_MOUNTEDSD卡已经挂载,可用
MEDIA_UNKNOWN不能识别SD卡
MEDIA_MOUNTED_READ_ONLY只读状态
MEDIA_UNMOUNTEDSD卡存在但是没有挂载
MEDIA_REMOVEDSD卡已经移除
MEDIA_CHECKINGSD卡正在准备
方法说明
getExternalStorageDirectory()获取外部存储路径
getExternalStoragePublicDirectory()获取public的外部路径
getExternalFilesDir()获取私有的外部路径
getDataDirectory()rom内存

七、使用SQLite数据库

数据库文件会存放在/data/data/<package name>/databases/目录下

1、SQLiteOpenHelper

创建数据库的辅助类

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

private static final String DB_NAME = "user.db";
private static final int VERSION = 1;

public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
//name:数据库名称,version:数据库版本,factory:游标工厂
}

public MySQLiteOpenHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
//数据库创建
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person (_id integer primary key autoincrement, " +
"name char(10), phone char(20), money integer(20))");
}
//数据库升级
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
}
}


数据库SQLiteDatabase

常用的一些方法

方法说明
execSQL()执行SQL语句实现增删操作
Cursor rawQuery()执行sql语句查询数据库
insert()往数据库插入数据
delete()从数据库删除数据
update()更新数据库
query()查询数据
beginTransaction()开始事务
setTransactionSuccessful()设置事务成功
endTransaction()结束事务

查询数据库

db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit);


参数意义

参数意义
table表名
columns查询的字段
selection查询条件,对应sql语句的where条件
selectionArgs填充查询条件的占位符
groupBy分组参数
having分组条件
orderBy排序,“字段名 desc/ ASC”
limit分页查询,“m,n”,m表示从第几条开始查,n表示一个查询多少条数据
select * from blacknumber limit pagesize offset startindex
//pageSize每页有多少条数据,startIndex 从哪条数据开始


游标Cursor

保存查询数据库的结果,原理有点像迭代器

方法功能描述
moveToNext()移动到下一个数据
moveToFirst()移动到第一个数据
moveToPrevious()移动到前一个数据
moveToLast()移动到下一个数据
getString()获取String类型的值
getInt()获取int类型的值
getColumnIndex()获取列索引
getColumnNames()获取所有字段名字
getCount()获取数据的个数

事务Transaction

使用事务会大大提高批量处理的效率

try {
//开启事务
db.beginTransaction();
...........
//设置事务执行成功
db.setTransactionSuccessful();
} finally{
//关闭事务
//如果此时已经设置事务执行成功,则sql语句生效,否则不生效
db.endTransaction();
}


android的数据持久化方式分为五种:

数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式。

当面试官问道我们这个问题的时候,回答的思路一般是这样的。

首先常见的持久化方式有五种:分别是:

1 使用SharedPreferences存储数据;

2 文件存储数据;xml,json

3 SQLite数据库存储数据;

4 使用ContentProvider存储数据;

5 网络存储数据;

(然后抽取其中的一个分开讲解)比如sqlite。

首先我们要讲解。1。sqlite为什么要用 2. sqlite有那些特点 3 。我们项目中又如何的运用

第一个问题,我们什么时候要使用数据库呢,那些条件,那些数据要使用呢,要条分缕析的吧这些东西讲清楚,那我在这里有个总结了:

有三种情况下我们要使用sqlite。1。数据量不是特别大的时候,为什么呢,数据量特别大的时候,一般都是些图片视频,这些其实都是用文件存储的,数据量比较小的时候,其实可以直接在代码中写死,比如写一个static常量,来存储这些内容。

2. 复杂关系型数据,当数据关系不是很复杂的时候,单一键值对关系,我么可以用,map来存储,或者用sp

3.数据更新不是特别快,也不是特别慢的时候,特别快的时候,我们会要频繁的update数据库,需要消耗大量资源,我们可以直接从网络上面获取即可。

数据跟新特别吗难道时候,同样我们可以写死。

接下来,就是数据库的特点了。

数据库的特点,我在这里截图说明:



分别介绍这些数据库的特点。

3. 最后我们要结合项目。

比如我们的sqlite,我这个应用中有这样一个需求,做一个数据插入,有10万条数据,我插入的时候第一次是300ms,后来,我用了下事务,时间到了26ms。

这就是我在这里用的。

也可以在sqlite的特性存储的时候,拙自己项目中这里符合这样的特点,就用了sqllite。

这就叫做结合项目。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: