前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android基础总结(5)——数据存储,持久化技术

Android基础总结(5)——数据存储,持久化技术

作者头像
mukekeheart
发布2018-02-27 14:50:30
1.2K0
发布2018-02-27 14:50:30
举报
  • 瞬时数据:指那些存储在内存当中,有可能会因为程序广播或其他原因导致内存被回收而丢失的数据。
  • 数据持久化:指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不丢失。

  保存在内存中的数据是瞬时数据,保存在手机设备中的数据是处于持久状态的,持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行切换。

1、持久化技术有哪些

  Android系统中主要提供了三种方式用于简单地实现数据持久化功能:

  1. 文件存储:是Android中最基本的一种数据存储方式。不对存储内容做任何的格式化处理,所有数据都是原封不动地保存到文件中。因此,这种方式比较适合存储一些文本数据或二进制数据。如果你想使用文件存储的方式来保存比较复杂的文本数据,则需要自己定义一套格式规范,这样方便之后将数据从文件中重新解析出来。
  2. SharedPreferences存储:使用键值对的方式存储数据。也就是说当保存一条数据时,需要给这条数据提供一个对应的键,这样在读取数据时就可以通过这个键把相应的值取出来。此外,SharedPreference还支持多种不同数据类型的存储。
  3. 数据库存储: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/目录下。主要步骤如下:
  1. 首先需要获取到SharedPreferences对象。Android中主要提供了三种方法用于得到SharedPreferences对象:
    1. Context类中的getSharedPreferences(String name, int mode)方法:此方法接收两个参数,第一个参数用于指定SharedPreference文件的名称,如果指定的文件不存在则会创建一个。第二个参数指定操作模式,主要有两种模式可选:MODE_PRIVATEMODE_MULTI_PROCESS,MODE_PRIVATE仍然是默认选项,表示只有当前应用程序可以对这个SharedPreference文件进行读写;MODE_MULTI_PROCESS则一般是用于会有多个进程对同一个SharedPreferences进行读写的情况。类似地,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE也已经被废弃使用了。
    2. Activity类中的getPreferences(int mode)方法:这个方法和第一个很相似,它只接收一个参数,就是操作模式。因为使用该方法会自动将当前活动的类名作为SharedPreferences文件的文件名。
    3. PreferenceManager类中的getDefaultSharedPreferences(Context context)方法:这是一个静态方法,它接收一个context参数,并自动当前应用程序的包名作为前缀名来命名SharedPreferences文件。
  2. 得到SharedPreferences对象之后,我们就可以开始往SharedPreference文件中写数据了,需要按照以下三个步骤来进行:
    1. 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象editor
    2. 向上一步获取的SharedPreferences.Editor对象中添加数据,比如添加一个boolean型数据就使用editor.putBoolean(String key, boolean value)方法,添加字符串就使用editor.putString(String key, String value)方法,以此类推。
    3. 最后所有数据添加完成之后调用editor.commit()方法将调价的数据进行提交。如果不进行commit(),则之前添加的数据将不会修改到文件中去
  • 从SharedPreferences中读取数据:从SharedPreferences类中我们可以看到有一系列get方法,显然,我们从SharedPreferences中读取数据是通过这些get方法来完成的。值得注意的是:这些get方法均接收两个参数,第一个是String类型的key,传入存储数据时使用的键就可以得到相应的值,第二个则是我们参数是默认值,即表示当我们传入的键找不到对应的值时,会以什么样的默认值进行返回。具体步骤如下:
    1. 获取SharedPreferences对象
    2. 调用SharedPreferences对象的get方法获取数据,例如读取boolean类型数据就使用getBoolean(String key, boolean defValue) 方法进行获取

4、SQLite数据库存储

  • 创建SQLiteOpenHelper对象:Android为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类我们可以非常简单地对数据库进行创建和升级了。
  • SQLiteOpenHelper是一个抽象类,使用它时我们自己的类必须实现其两个抽象方法onCreate(SQLiteDatabase db)方法onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,分别实现创建和升级数据库的逻辑。
代码语言:js
复制
 1 public class CoolWeatherOpenHelper extends SQLiteOpenHelper {
 2     
 3     /**
 4      *  Province表建表语句
 5      */
 6     public static final String CREATE_PROVINCE = "create table Province ("
 7                 + "id integer primary key autoincrement, " 
 8                 + "province_name text, "
 9                 + "province_code text)";
10     /**
11      *  City表建表语句
12      */
13     public static final String CREATE_CITY = "create table City ("
14                 + "id integer primary key autoincrement, " 
15                 + "city_name text, " 
16                 + "city_code text, " 
17                 + "province_id integer)";
18     /**
19      *  County表建表语句
20      */
21     public static final String CREATE_COUNTY = "create table County ("
22                 + "id integer primary key autoincrement, " 
23                 + "county_name text, " 
24                 + "county_code text, " 
25                 + "city_id integer)";
26 
27     public CoolWeatherOpenHelper(Context context, String name, CursorFactory factory,
28             int version) {
29         super(context, name, factory, version);
30     }
31 
32     @Override
33     public void onCreate(SQLiteDatabase db) {
34         db.execSQL(CREATE_PROVINCE);  // 创建Province表
35         db.execSQL(CREATE_CITY);  // 创建City表
36         db.execSQL(CREATE_COUNTY);  // 创建County表
37     }
38 
39     @Override
40     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
41         //调用db.execSQL()方法执行数据库的更新和升级,
42         
43         onCreate(db) ;  //重新创建数据库
44     }
45 }
  • 创建数据库:得到SQLiteOpenHelper对象之后,我们可以利用其public SQLiteDatabase getReadableDatabase() 方法或public SQLiteDatabase getWritableDatabase()方法来创建我们的数据库,并且获得了一个数据库对象,后面我们可以利用这个数据库对象对我们创建的数据库进行各种增删查改操作。
代码语言:js
复制
1 public class CoolWeatherDB {
 2 
 3     // 数据库名
 4     public static final String DB_NAME = "cool_weather" ;
 6     // 数据库版本
 7     public static final int VERSION = 1;
 8 
 9     private static CoolWeatherDB coolWeatherDB;
10 
11     private SQLiteDatabase db;
12 
13     // 将构造方法私有化
14     private CoolWeatherDB(Context context) {
15         // 创建帮助类对象
16         CoolWeatherOpenHelper dbHelper = new CoolWeatherOpenHelper(context,DB_NAME, null, VERSION);
18          // 创建数据库
19         db = dbHelper.getWritableDatabase();
20     }
21 
22     // 获取CoolWeatherDB的实例。
23     public synchronized static CoolWeatherDB getInstance(Context context) {
24         if (coolWeatherDB == null) {
25             coolWeatherDB = new CoolWeatherDB(context);
26         }
27         return coolWeatherDB;
28     }    
29 } 
  • 对数据库的操作CRUD,即增删查改。这里我们利用上面得到的SQLiteDatabase数据库对象提供的各种方法来进行相关的操作。
    • Create:创建、添加。利用SQLiteDatabase数据库对象insert(String table, String nullColumnHack, ContentValues values)方法实现添加数据:第一个参数是数据库中的表名,第二个一般直接传入null即可,第三个参数是一个ContentValues对象,它提供了一系列的put()方法的重载,用于向ContentValues对象中添加数据,只需将表中的每个列名以及相应的待添加的数据传入即可。ContentValues的底层是一个HashMap集合,键即为对应表中的各列的名称,值是我们传入的数据。
代码语言:js
复制
 1 /**
 2  * 将County实例存储到数据库。
 3  */
 4 public void saveCounty(County county) {
 5     if (county != null) {
 6         ContentValues values = new ContentValues();
 7         values.put("county_name", county.getCountyName());
 8         values.put("county_code", county.getCountyCode());
 9         values.put("city_id", county.getCityId());
10         db.insert("County", null, values);
11     }
12 }
代码语言:js
复制
 1 /**
 2  * 对存储到数据库的County实例进行更新。
 3  */
 4 public void updateCounty(County county) {
 5     if (county != null) {
 6         ContentValues values = new ContentValues();
 7         values.put("county_name", "beijing");
 8         values.put("county_code", "001");
 9         db.update("County", values, "city_id = ?", new String [] {"010201"}) ;
10     }
11 }
代码语言:js
复制
 1 /**
 2  * 删除存储到数据库中的某些County实例。
 3  */
 4 public void deleteCounty(County county) {
 5  6         db.delete("County", "county_name = ? ", new String [] {"beijing"}) ; 7 }

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

指定查询结果的排序方式

代码语言:js
复制
 1 /**
 2  * 从数据库读取某城市下所有的县信息。
 3  */
 4 public List<County> loadCounties(int cityId) {
 5     List<County> list = new ArrayList<County>();
 6     Cursor cursor = db.query("County", null, "city_id = ?",
 7             new String[] { String.valueOf(cityId) }, null, null, null);
 8     if (cursor.moveToFirst()) {
 9         do {
10             County county = new County();
11             county.setId(cursor.getInt(cursor.getColumnIndex("id")));
12             county.setCountyName(cursor.getString(cursor
13                     .getColumnIndex("county_name")));
14             county.setCountyCode(cursor.getString(cursor
15                     .getColumnIndex("county_code")));
16             county.setCityId(cityId);
17             list.add(county);
18         } while (cursor.moveToNext());
19     }
20     return list;
21 }
  • 对数据的操作还可以直接使用SQL来操作数据库
代码语言:js
复制
 1 public void operateSQL(){
 2     //插入
 3     db.execSQL("insert into Country (country_name, country_code, city_id) values (?,?,?)",new String [] {"beijing","001","111"});
 4     //更新
 5     db.execSQL("update Country set country_name = ? where country_code = ?", new String [] {"beijing","002"});
 6     //删除
 7     db.execSQL("delete from Country where contry_code = ?", new String [] {"002"});
 8     //查询,注意:查询是用的rawQuery()方法,不再是execSQL()方法
 9     db.rawQuery("select * from Country", null) ;    
10 }

5、数据库的事务特性

  •  数据库的事务特性就是 ACID.
    1. Atomicity:原子性
    2. Consistancy:一致性
    3. Isolation:隔离性
    4. Durabolity:持久性
  • SQLite是支持事务特性的,事务特性可以保证让某一系列的操作要么全部完成,要么一个都不完成。其标准用法是利用SQLiteDatabase数据库对象提供的public void beginTransaction()方法和public void endTransaction()方法进行开启和结束一个事务,然后该事物中的所有关于数据库的操作就都在开启和结束中间完成。此外, public void setTransactionSuccessful()方法表示事务已经执行成功。
代码语言:js
复制
 1 public void operateSQL() {
 2     db.beginTransaction() ;
 3     try {
 4         // 插入
 5         db.execSQL("insert into Country (country_name, country_code, city_id) values (?,?,?)",
 6                 new String[] { "beijing", "001", "111" });
 7         // 更新
 8         db.execSQL("update Country set country_name = ? where country_code = ?", new String[] { "beijing", "002" });
 9         // 删除
10         db.execSQL("delete from Country where contry_code = ?", new String[] { "002" });
11         // 查询,注意:查询是用的rawQuery()方法,不再是execSQL()方法
12         db.rawQuery("select * from Country", null) ;
13         //如果在endTransaction()执行之前没有执行setTransactionSuccessful()方法的话表明事务执行失败,
14         //所以所有操作一条都不完成
15         db.setTransactionSuccessful() ;
16     } catch (Exception e) {
17         // TODO: handle exception
18     }finally{
19         db.endTransaction() ;
20     }    
21 }

如果在endTransaction()执行之前没有执行setTransactionSuccessful()方法的话表明事务执行失败,所以所有操作一条都不完成。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-07-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、持久化技术有哪些
  • 2、文件存储
  • 3、SharedPreferences存储
  • 4、SQLite数据库存储
  • 5、数据库的事务特性
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档