所有应用程序必然有数据的输入输出,Android也是一样的,Android应用程序的参数设置、运行状态数据这些都需要保存到外部存储器上,保证关机后数据不丢失,如下是几种Android常见的数据存储方式: SharedPreferences:适合保存少量数据(一些配置信息、积分之类);SQLite:一个真正轻量级数据库,没有后台进程,整个数据库就对应于一个文件,适合大量数据需要存储、访问的情况。下来详细来看看它们的用法。Android系统主要提供了3种方式用于简单地实现数据持久化功能,即文件存储、SharedPreferences存储以及SQLite数据库存储。
1.文件存储
文件存储是Android中最基本的一种数据存储方式,它不对存储的内容做任何的格式化处理,所有数据都是原封不动地保存到文件当中,比较适合用于存储一些简单的文本数据或二进制数据,不适合存储一些较为复杂的文本数据。
1.将数据存储到文件中
Context 类提供了openFileOutput()方法,用于将数据存储到指定的文件中。所有的文件默认都是存储在 /data/data/< packagename>/files 目录下的。
public void save(String inputText) {
FileOutputStream out = null;
BufferedWriter writer = null; try { // 两种模式,MODE_PRIVATE:默认私有,指定相同文件名则覆盖原文件内容;MODE_APPEND:指定相同文件名则追加内容。
// 其实还有MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE两种模式,因为安全因素已经在 Android4.2中被弃用。
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
} catch (IOException e) {
e.printStackTrace();
} finally { try { if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}1234567891011121314151617181920212.从文件中读取数据
Context 类提供了openFileInput()方法,用于从文件中读取数据,只接受一个参数 文件名,系统会自动加载存储目录下的这个文件,并返回一个 FileInputStream 对象。
public String load() {
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder(); try {
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = ""; while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally { if (reader != null) { try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} return content.toString();
}1234567891011121314151617181920212223242.SharedPreferences存储
不同于文件存储,SharedPreferences是使用 键值对 的方式来存储数据的。
1.SharedPreferences接口
主要负责读取应用程序的Preferences数据,提供了如下常见方法来访问SharedPreferences中的key-value对:
boolean contains(String key) // 判断是否包含key对应的数据 abstract Map<String, ?> getAll() // 获取全部key-value对 boolean getXxx(String key, xxx defValue) // 获取指定key的value值1234
2.将数据存储到SharedPreferences中
要想使用SharedPreferences来存储数据,首先需要获取到SharedPreferences对象,Android主要提供了3种方法用于获取SharedPreferences对象:
1)Context 类中的 getSharedPreferences()方法; 2)Activity 类中的 getPreferences()方法; 3)PreferenceManager 类中的 getDefaultSharedPreferences()方法。1234
SharedPreferences数据总是以xml格式存储在 /data/data/< packagename>/shared_prefs 目录下的。
// SharedPreferences接口本身没有写入数据的能力,而是通过内部接口,调用edit()方法即获取Editor对象SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "USER_NAME");
editor.putInt("age", 25);
editor.apply(); // 除此之外,Editor对象还包含clear()和remove(String key)等方法123453.从SharedPreferences中读取数据
SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");int age = pref.getInt("age", 0);1233.SQLite数据库存储
SQLite是一个嵌入式的数据库引擎,适用于资源有限的设备上适量存取数据(SQLite数据库只是一个文件)。SQLiteDatabase表示一个数据库(底层是一个数据库文件),Android通过SQLiteDatabase对象来管理、操作数据库。
1.创建SQLite数据库
SQLiteDatabaseHelper类可用于管理数据库的创建和版本更新,SQLiteDatabaseHelper包含如下常用方法:
getReadableDatabase() // 以读写的方式打开数据库对应的SQLiteDatabase对象 getWritableDatabase() // 以写的方式打开数据库对应的SQLiteDatabase对象 onCreate(SQLiteDatabase db) // 第一次创建回调 onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) // 当数据库版本更新时回调 close() // 关闭所有打开的SQLiteDatabase123456
继承SQLiteOpenHelper,创建MyDatabaseHelper数据库帮助类:
public class MyDatabaseHelper extends SQLiteOpenHelper {
/**
* integer表示整型,real表示浮点型,text表示文本类型,blob表示二进制类
* primary key表示将id设为主键,并用auto_increment键字表示id是自增长的
*/
private static final String CREATE_TABLE_PERSON = "create table person(" + "id integer primary key autoincrement," + "name text," + "age integer)"; private Context mContext; /**
* 构造方法
*
* @param context 上下文
* @param name 数据库名,创建数据库时使用的就是这里的名称
* @param factory 允许我们在查询数据时返回一个自定义的Cursor,一般传入null
* @param version 数据库版本号
*/
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version);
mContext = context;
} /**
* 创建数据库
*
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_PERSON);
} /**
* 升级数据库
*
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}12345678910111213141516171819202122232425262728293031323334353637383940414243然后就可以在应用程序中创建数据库了:
MyDatabaseHelper dbHelper = new MyDatabaseHelper(this, "person.db", null, 1); dbHelper.getWritableDatabase();12
升级数据库只需要将版本号增加,然后 onUpgrade() 方法就可以被执行了。
2.SQLite数据库的增删改查
我们对数据库的操作无非4种:CRUD:
C Create 添加 insert R Retrieve 查询 select U Update 更新 update D Delete 删除 delete12345
首先创建数据库表的实体类PersonBean:
public class PersonBean {
private String name; private int age; public String getName() { return name;
} public void setName(String name) { this.name = name;
} public int getAge() { return age;
} public void setAge(int age) { this.age = age;
}
}12345678910111213141516前面我们知道,调用 SQLiteOpenHelper 的 getReadableDatabase() 或 getWritableDatabase() 方法可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个 SQLiteDatabase 对象,借助这个对象就可以对数据进行 CRUD 操作了。
SQLiteDatabase db = dbHelper.getWritableDatabase();1
接下来将数据库person表的增删改查操作封装起来,如下PersonDB:
public class PersonDB {
private MyDatabaseHelper dbHelper; public PersonDB(Context context){
dbHelper = new MyDatabaseHelper(context, "person.db", null, 1);
} /**
* 增
*/
public boolean add(PersonBean bean){
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", bean.getName());
values.put("age", bean.getAge()); /**
* 执行插入,返回值(如果插入成功将插入成功的行号返回,失败返回-1)
* table: 表名
* nullColumnHack: 一般传null
* values: 表中添加的一行的数据内容, ContentValues以Map封装
*/
long result = db.insert("person", "null", values); // 内部在拼装sql语句
// 关闭数据库
db.close(); if (result == -1) { return false;
} return true;
} /**
* 删
*/
public int delete(String name){
SQLiteDatabase db = dbHelper.getWritableDatabase(); /**
* table: 表名
* whereClause: 删除条件
* whereArgs: 删除条件占位符的参数
* 返回值是: 成功删除了多少行
*/
int result = db.delete("person", "name = ?", new String[]{name}); // 关闭数据库
db.close(); return result;
} /**
* 改
*/
public int update(PersonBean bean){
SQLiteDatabase db = dbHelper.getWritableDatabase(); /**
* table: 表名
* values: 更改字段的内容, 以map封装
* whereClause: 更新条件
* whereArgs: 更新条件占位符的参数
* sql: update person set age=18 where name='zhangsan';
*/
ContentValues values = new ContentValues();
values.put("age", bean.getAge()); // 返回的值: 成功修改了多少行
int result = db.update("person", values, "name = ?", new String[]{bean.getName()}); // 关闭数据库
db.close(); return result;
} /**
* 查
*/
public PersonBean query(String name){
SQLiteDatabase db = dbHelper.getReadableDatabase();
PersonBean bean = new PersonBean(); /**
* table: 指定查询的表名
* columns: 指定查询的列名(null:查询所有)
* selection: 指定where的约束条件
* selectionArgs: 为where中的占位符提供具体的值
* groupBy: 指定需要group by的列
* having: 对group by后的结果进一步约束
* orderBy: 指定查询结果的排序方式
*/
Cursor cursor = db.query("person", new String[]{"id","name","age"}, "name = ?", new String[] {name}, null, null, "id desc"); /**
* 判断结果集中是否有数据
*/
if(cursor != null && cursor.getCount() >0){ // 循环遍历结果集获取结果集的内容
while(cursor.moveToNext()){ // 获取这一行上所有的数据内容
int id = cursor.getInt(0);
bean.setName(cursor.getString(1));
bean.setAge(Integer.parseInt(cursor.getString(2)));
}
} // 关闭数据库
db.close(); return bean;
}
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697到此我们就可以通过创建PersonDB的实例,调用该实例的方法来增删改查数据库person表了:
PersonDB personDB = new PersonDB(context);// 增PersonBean bean = new PersonBean();
bean.setName("zhangsan");
bean.setAge(20);
personDB.add(bean);// 删personDB.delete("zhangsan");// 改PersonBean bean = new PersonBean();
bean.setName("zhangsan");
bean.setAge(25);
personDB.update(bean);// 查PersonBean bean = personDB.query("zhangsan");1234567891011121314154.使用SQL操作数据库
首先打开数据库对应的 SQLiteDatabase 对象:
MyDatabaseHelper dbHelper = new MyDatabaseHelper(context, "person.db", null, 1); SQLiteDatabase db = dbHelper.getWritableDatabase();12
然后我们就可以直接使用 SQL语句 操作数据库:
// 增db.execSQL("insert into person (name ,age) values (?, ?)", new String[]{"wangwu","26"});// 删db.execSQL("delete from person where age>?", new String[]{"20"});// 改db.execSQL("update person set age=? where name=?", new String[]{"19", "wangwu"});// 查db.rawQuery("select * from person", null);123456785.使用数据库开源库操作数据库
现在公司里的代码非常强调稳定性,而我们自己写出的代码往往结构越复杂就越容易出现问题,相反,开源项目的代码都是经过时间验证的,通常比我们自己的代码要稳定的多。因此,现在很多公司为了追求开发效率以及项目的稳定性,都会选择使用开源库。
| 数据库开源库 | 说明 | 地址 |
|---|---|---|
| DBFlow | 一个基于AnnotationProcessing(注解处理器)的强大、健壮同时又简单的ORM框架 | https://github.com/Raizlabs/DBFlow |
| OrmLite | JDBC和Android的轻量级ORM java包 | https://github.com/j256/ormlite-android |
| Sugar | 用超级简单的方法处理Android数据库 | https://github.com/satyan/sugar |
| GreenDao | 一种轻快地将对象映射到SQLite数据库的ORM解决方案 | https://github.com/greenrobot/greenDAO |
| ActiveAndroid | 以活动记录方式为Android SQLite提供持久化 | https://github.com/pardom/ActiveAndroid |
| SQLBrite | SQLiteOpenHelper和ContentResolver的轻量级包装 | https://github.com/square/sqlbrite |
| Realm | 移动数据库:一个SQLite和ORM的替换品 | https://github.com/realm/realm-java |
共同学习,写下你的评论
评论加载中...
作者其他优质文章