Android基础总结(5)——数据存储,持久化技术
- 瞬时数据:指那些存储在内存当中,有可能会因为程序广播或其他原因导致内存被回收而丢失的数据。
- 数据持久化:指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不丢失。
保存在内存中的数据是瞬时数据,保存在手机设备中的数据是处于持久状态的,持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行切换。
1、持久化技术有哪些
Android系统中主要提供了三种方式用于简单地实现数据持久化功能:
- 文件存储:是Android中最基本的一种数据存储方式。不对存储内容做任何的格式化处理,所有数据都是原封不动地保存到文件中。因此,这种方式比较适合存储一些文本数据或二进制数据。如果你想使用文件存储的方式来保存比较复杂的文本数据,则需要自己定义一套格式规范,这样方便之后将数据从文件中重新解析出来。
- SharedPreferences存储:使用键值对的方式存储数据。也就是说当保存一条数据时,需要给这条数据提供一个对应的键,这样在读取数据时就可以通过这个键把相应的值取出来。此外,SharedPreference还支持多种不同数据类型的存储。
- 数据库存储:SQLite是一款轻量级的关系型数据库,运算速度快,占用资源少,通常只需要几百k就可以了。不仅支持标准的SQL语法,还遵循了数据库的ACID事务。
此外,我们还可以通过将数据存储到SD卡中。不过使用上述三种方式会更加简单一些,而且也更加安全。
2、文件存储
- 将数据保存到文件:利用Context类中的openFileOutput(String fileName, int mode)方法可以将数据存储到指定的文件中,该方法返回一个FileOutputStream对象,得到该对象之后,使用Java流的方式将内容写入文件中。该方法接收两个参数:
- 第一个参数是文件名,在文件创建的时候使用的就是这个文件名,注意,这里指定的文件名不可以包含路径,因为所有的文件都默认存储到/data/data/<packageName>/files/目录下的。
- 第二个参数是文件的操作模式,主要有两种可选模式,MODE_PRIVATE和MODE_APPEND,其中MODE_PRIVATE是默认操作模式,表示当指定同样文件名的时候,所写入的内容会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已经存在,则将新内容追加到原文件内容的后面。此外,还有两种可选模式,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,分别表示允许其他应用程序对我们程序中的文件进行读写操作,不过由于这两种操作模式过于危险,很容易引起安全性漏洞,已经被废弃。
- 从文件中读取数据:同样利用Context类中的openFileInput(String fileName)方法可以将数据存储到指定的文件中,该方法返回一个FileInputStream对象,得到该对象之后,使用Java流的方式将文件中的内容读出。该方法只接收一个参数,就是文件名,然后系统会自动从/data/data/<packageName>/files/目录下去加载这个文件,并返回一个FileInputStream对象。
文件存储的方式并不适用于保存一些较为复杂的文本数据。
3、SharedPreferences存储
- 通过SharedPreferences存储数据:SharedPreference存储的数据都以xml格式存储,并且都自动保存到/data/data/<packageName>/shared_prefs/目录下。主要步骤如下:
- 首先需要获取到SharedPreferences对象。Android中主要提供了三种方法用于得到SharedPreferences对象:
- Context类中的getSharedPreferences(String name, int mode)方法:此方法接收两个参数,第一个参数用于指定SharedPreference文件的名称,如果指定的文件不存在则会创建一个。第二个参数指定操作模式,主要有两种模式可选:MODE_PRIVATE和MODE_MULTI_PROCESS,MODE_PRIVATE仍然是默认选项,表示只有当前应用程序可以对这个SharedPreference文件进行读写;MODE_MULTI_PROCESS则一般是用于会有多个进程对同一个SharedPreferences进行读写的情况。类似地,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE也已经被废弃使用了。
- Activity类中的getPreferences(int mode)方法:这个方法和第一个很相似,它只接收一个参数,就是操作模式。因为使用该方法会自动将当前活动的类名作为SharedPreferences文件的文件名。
- PreferenceManager类中的getDefaultSharedPreferences(Context context)方法:这是一个静态方法,它接收一个context参数,并自动当前应用程序的包名作为前缀名来命名SharedPreferences文件。
- 得到SharedPreferences对象之后,我们就可以开始往SharedPreference文件中写数据了,需要按照以下三个步骤来进行:
- 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象editor
- 向上一步获取的SharedPreferences.Editor对象中添加数据,比如添加一个boolean型数据就使用editor.putBoolean(String key, boolean value)方法,添加字符串就使用editor.
putString(String key, String value)方法,以此类推。
- 最后所有数据添加完成之后调用editor.commit()方法将调价的数据进行提交。如果不进行commit(),则之前添加的数据将不会修改到文件中去。
- 从SharedPreferences中读取数据:从SharedPreferences类中我们可以看到有一系列get方法,显然,我们从SharedPreferences中读取数据是通过这些get方法来完成的。值得注意的是:这些get方法均接收两个参数,第一个是String类型的key,传入存储数据时使用的键就可以得到相应的值,第二个则是我们参数是默认值,即表示当我们传入的键找不到对应的值时,会以什么样的默认值进行返回。具体步骤如下:
- 获取SharedPreferences对象
- 调用SharedPreferences对象的get方法获取数据,例如读取boolean类型数据就使用
getBoolean(String key, boolean defValue)
方法进行获取
4、SQLite数据库存储
- 创建SQLiteOpenHelper对象:Android为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类我们可以非常简单地对数据库进行创建和升级了。
- SQLiteOpenHelper是一个抽象类,使用它时我们自己的类必须实现其两个抽象方法onCreate(SQLiteDatabase db)方法和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,分别实现创建和升级数据库的逻辑。
public class CoolWeatherOpenHelper extends SQLiteOpenHelper { /**
* Province表建表语句
*/
public static final String CREATE_PROVINCE = "create table Province ("
+ "id integer primary key autoincrement, "
+ "province_name text, "
+ "province_code text)";
/**
* City表建表语句
*/
public static final String CREATE_CITY = "create table City ("
+ "id integer primary key autoincrement, "
+ "city_name text, "
+ "city_code text, "
+ "province_id integer)";
/**
* County表建表语句
*/
public static final String CREATE_COUNTY = "create table County ("
+ "id integer primary key autoincrement, "
+ "county_name text, "
+ "county_code text, "
+ "city_id integer)"; public CoolWeatherOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_PROVINCE); // 创建Province表
db.execSQL(CREATE_CITY); // 创建City表
db.execSQL(CREATE_COUNTY); // 创建County表
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//调用db.execSQL()方法执行数据库的更新和升级, onCreate(db) ; //重新创建数据库
}
}
- SQLiteOpenHelper是一个抽象类,使用它时我们自己的类必须实现其两个抽象方法onCreate(SQLiteDatabase db)方法和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,分别实现创建和升级数据库的逻辑。
- 然后利用其构造方法public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version)来创建对象SQLiteOpenHelper对象
- 其中第一个参数是context,必须要有它才能对数据库进行操作;
- 第二个参数是数据库名,创建数据库时使用的就是这里指定的名称;
- 第三个参数是允许我们在查询数据时候返回一个自定义的Cursor,一般都传入null;
- 第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。当前版本号和之前的版本号不同时,onUpgrade()方法就会得到执行
- 创建数据库:得到SQLiteOpenHelper对象之后,我们可以利用其public SQLiteDatabase getReadableDatabase() 方法或public SQLiteDatabase getWritableDatabase()方法来创建我们的数据库,并且获得了一个数据库对象,后面我们可以利用这个数据库对象对我们创建的数据库进行各种增删查改操作。
public class CoolWeatherDB { // 数据库名
public static final String DB_NAME = "cool_weather" ;
// 数据库版本
public static final int VERSION = 1; private static CoolWeatherDB coolWeatherDB; private SQLiteDatabase db; // 将构造方法私有化
private CoolWeatherDB(Context context) {
// 创建帮助类对象
CoolWeatherOpenHelper dbHelper = new CoolWeatherOpenHelper(context,DB_NAME, null, VERSION);
// 创建数据库
db = dbHelper.getWritableDatabase();
} // 获取CoolWeatherDB的实例。
public synchronized static CoolWeatherDB getInstance(Context context) {
if (coolWeatherDB == null) {
coolWeatherDB = new CoolWeatherDB(context);
}
return coolWeatherDB;
}
}
- 对数据库的操作:CRUD,即增删查改。这里我们利用上面得到的SQLiteDatabase数据库对象提供的各种方法来进行相关的操作。
- Create:创建、添加。利用SQLiteDatabase数据库对象insert(String table, String nullColumnHack, ContentValues values)方法实现添加数据:第一个参数是数据库中的表名,第二个一般直接传入null即可,第三个参数是一个ContentValues对象,它提供了一系列的put()方法的重载,用于向ContentValues对象中添加数据,只需将表中的每个列名以及相应的待添加的数据传入即可。ContentValues的底层是一个HashMap集合,键即为对应表中的各列的名称,值是我们传入的数据。
/**
* 将County实例存储到数据库。
*/
public void saveCounty(County county) {
if (county != null) {
ContentValues values = new ContentValues();
values.put("county_name", county.getCountyName());
values.put("county_code", county.getCountyCode());
values.put("city_id", county.getCityId());
db.insert("County", null, values);
}
} - Update:更新。利用SQLiteDatabase数据库对象提供的update(String table, ContentValues values, String whereClause, String[] whereArgs)方法实现更新数据库中的数据。第一个参数就是表名,第二个是要更新的数据组装成的ContentValues对象,第三个和第四个参数用于约束更新某一行或某几行的数据,不指定的话是默认更新所有行。
/**
* 对存储到数据库的County实例进行更新。
*/
public void updateCounty(County county) {
if (county != null) {
ContentValues values = new ContentValues();
values.put("county_name", "beijing");
values.put("county_code", "001");
db.update("County", values, "city_id = ?", new String [] {"010201"}) ;
}
}第三个参数对应的是SQL语句中的where部分,表示去更新所有city_id = ?的行,而?是一个占位符,可以通过第四个参数提供的一个字符串组为第三个参数中的每个站位符指定相应的内容。
- Delete:删除。利用SQLiteDatabase数据库对象提供的delete(String table, String whereClause, String[] whereArgs)方法实现删除数据库中的数据。各项参数前面都已经介绍过,就不一一介绍了。
/**
* 删除存储到数据库中的某些County实例。
*/
public void deleteCounty(County county) {
db.delete("County", "county_name = ? ", new String [] {"beijing"}) ; } - Retrieve:查询。利用SQLiteDatabase数据库对象提供的public Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy)方法实现查询数据库中的数据。该方法返回一个Cursor游标对象,查询到的所有数据都将从这个对象中取出。
query()方法参数 对应的SQL部分 描述 table from table_name 指定查询表名 columns select column1, column2 指定查询列名 selection where column = value 指定where约束条件 selectionArgs ---- 为where中的占位符提供具体的值 groupBy group by column 指定需要group by的列 having having column = value 对group by的结果进行进一步的约束 orderBy order by column1, column2 指定查询结果的排序方式 /**
* 从数据库读取某城市下所有的县信息。
*/
public List<County> loadCounties(int cityId) {
List<County> list = new ArrayList<County>();
Cursor cursor = db.query("County", null, "city_id = ?",
new String[] { String.valueOf(cityId) }, null, null, null);
if (cursor.moveToFirst()) {
do {
County county = new County();
county.setId(cursor.getInt(cursor.getColumnIndex("id")));
county.setCountyName(cursor.getString(cursor
.getColumnIndex("county_name")));
county.setCountyCode(cursor.getString(cursor
.getColumnIndex("county_code")));
county.setCityId(cityId);
list.add(county);
} while (cursor.moveToNext());
}
return list;
}
- Create:创建、添加。利用SQLiteDatabase数据库对象insert(String table, String nullColumnHack, ContentValues values)方法实现添加数据:第一个参数是数据库中的表名,第二个一般直接传入null即可,第三个参数是一个ContentValues对象,它提供了一系列的put()方法的重载,用于向ContentValues对象中添加数据,只需将表中的每个列名以及相应的待添加的数据传入即可。ContentValues的底层是一个HashMap集合,键即为对应表中的各列的名称,值是我们传入的数据。
- 对数据的操作还可以直接使用SQL来操作数据库:
public void operateSQL(){
//插入
db.execSQL("insert into Country (country_name, country_code, city_id) values (?,?,?)",new String [] {"beijing","001","111"});
//更新
db.execSQL("update Country set country_name = ? where country_code = ?", new String [] {"beijing","002"});
//删除
db.execSQL("delete from Country where contry_code = ?", new String [] {"002"});
//查询,注意:查询是用的rawQuery()方法,不再是execSQL()方法
db.rawQuery("select * from Country", null) ;
}
5、数据库的事务特性
- 数据库的事务特性就是 ACID.
- Atomicity:原子性
- Consistancy:一致性
- Isolation:隔离性
- Durabolity:持久性
- SQLite是支持事务特性的,事务特性可以保证让某一系列的操作要么全部完成,要么一个都不完成。其标准用法是利用SQLiteDatabase数据库对象提供的public void beginTransaction()方法和public void endTransaction()方法进行开启和结束一个事务,然后该事物中的所有关于数据库的操作就都在开启和结束中间完成。此外, public void setTransactionSuccessful()方法表示事务已经执行成功。
public void operateSQL() {
db.beginTransaction() ;
try {
// 插入
db.execSQL("insert into Country (country_name, country_code, city_id) values (?,?,?)",
new String[] { "beijing", "001", "111" });
// 更新
db.execSQL("update Country set country_name = ? where country_code = ?", new String[] { "beijing", "002" });
// 删除
db.execSQL("delete from Country where contry_code = ?", new String[] { "002" });
// 查询,注意:查询是用的rawQuery()方法,不再是execSQL()方法
db.rawQuery("select * from Country", null) ;
//如果在endTransaction()执行之前没有执行setTransactionSuccessful()方法的话表明事务执行失败,
//所以所有操作一条都不完成
db.setTransactionSuccessful() ;
} catch (Exception e) {
// TODO: handle exception
}finally{
db.endTransaction() ;
}
}如果在endTransaction()执行之前没有执行setTransactionSuccessful()方法的话表明事务执行失败,所以所有操作一条都不完成。
Android基础总结(5)——数据存储,持久化技术的更多相关文章
- Android 基础-3.0 数据存储方式
Android几种数据存储方式 文件存储 SharedPreference存储 Json解析 SQLite数据库存储 文件存储 文件存储是Android中最基本的一种存储方式,和Java中实现I/O的 ...
- Android:日常学习笔记(9)———探究持久化技术
Android:日常学习笔记(9)———探究持久化技术 引入持久化技术 什么是持久化技术 持久化技术就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失 ...
- Android学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储
前面一讲介绍了数据持久化技术的前两种:文件存储.SharedPreferences存储.下面介绍第三种技术:SQLite数据库存储 一.SQLite数据库存储 SQLite数据库是一款轻量级的关系型数 ...
- Android学习之基础知识九—数据存储(持久化技术)
数据持久化是将那些内存中的瞬时数据保存到存储设备,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失. Android系统中主要提供了3种方式用于简单地实现数据持久化功能:文件存储.SharedP ...
- 【读书笔记《Android游戏编程之从零开始》】20.游戏开发基础(游戏数据存储)
对于数据的存储,Android 提供了4种保存方式. (1)SharedPreference 此方法适用于简单数据的保持,文如其名,属于配置性质的保存,不适合比较大的情况,默认存放在手机内存里 (2) ...
- Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用
前言 啦啦啦各位小伙伴们许久不见了~学期末和过年期间自己忙着做其他事没能及时更新Android开发系列课程的博客,实在是罪过罪过~ 好啦~废话不多说,进入我们今天的主题.今天我们将和大家学习其他的数据 ...
- Android 学习笔记之数据存储SharePreferenced+File
学习内容: Android的数据存储.... 1.使用SharedPreferences来保存和读取数据... 2.使用File中的I/O来完成对数据的存储和读取... 一个应用程序,经常需要与用 ...
- Android开发手记(16) 数据存储一 SharedPreferences
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SharedPreferenc ...
- Android核心技术Intent和数据存储篇
女孩:上海站到了? 男孩:嗯呢?走向世界~ 女孩:Intent核心技术和数据存储技术? 男孩:对,今日就讲这个~ Intent是各个组件之间用来进行通信的,Intent的翻译为"意图&quo ...
- Android开发-API指南-数据存储
Storage Options 英文原文:http://developer.android.com/guide/topics/data/data-storage.html 采集日期:2015-02-0 ...
随机推荐
- Hadoop学习4--安装Hadoop
首先献上Hadoop下载地址: http://apache.fayea.com/hadoop/core/ 选择相应版本,点一下,直接进行http下载了. 对原来写的一篇文章,相当不满意,过于粗糙了,于 ...
- 3. redis的超时,事务,watch
一. 键的生存时间 expire设置一个已经存在的key的生存时间,到时间后redis自动删除这个 命令 expire 设置生存时间(单位/秒) pexpire设置生存时间(单位/毫秒) ttl/pt ...
- .net EntityFramework用法探索系列 1
EntityFramework用法探索系列 (一)DatabaseFirst (二)CodeFirst (三)CodeFirst流畅API (四)Repository和UnitOfWork (五)引入 ...
- (C/C++) Interview in English - Threading
Q. What's the process and threads and what's the difference between them? A. A process is an execut ...
- Scala第三章学习笔记
换行后的左大括号造成的问题: class FooHolder { def foo() { println("foo was called") } } Scala认为def foo( ...
- 在ScrollView中嵌入GridView
做android程序开发的都知道,不能在一个拥有Scrollbar的组件中嵌入另一个拥有Scrollbar的组件,因为这不科学,会混淆滑动事件,导致只显示一到两行数据.那么就换一种思路,首先让子控件的 ...
- BloomFilter–大规模数据处理利器(转)
BloomFilter–大规模数据处理利器 Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求1 ...
- ylbtech-LanguageSamples-Yield
ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Yield 1.A,示例(Sample) 返回顶部 “Yield”示例 本示例演示如何创 ...
- GC之三--GC 触发Full GC执行的情况及应对策略
1.System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数. ...
- 启动httpd服务:SSLCertificateFile: file '/var/www/miq/vmdb/certs/server.cer' does not exist or is empty
启动httpd服务,失败: [root@test vmdb]# service httpd restart Stopping httpd: [FAILED] Starting httpd: Synta ...