本文讲解Android中常用的持久化技术,包括SharedPreferences键值对存储方式、SQLite数据库持久化技术、LitePal开源数据库工具等。
数据持久化简单来说就是将内存中暂时存储的数据转存到设备的存储单元中,使得数据处于持久状态。
Android系统提供了3中方式简单的实现数据持久化功能,即简单文件存储、SharedPreferences存储、数据库存储。
简单文件存储就是以流的形式将数据存储到文件中,适用于简单的二进制数据,文本数据等。
private void savaData(String persistencePath,String content)
{
FileOutputStream outputStream=null;
BufferedWriter bufferedWriter=null;
try {
File file = new File(persistencePath);
outputStream=new FileOutputStream(file);
bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write(content);
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (outputStream!=null)
outputStream.close();
if (bufferedWriter!=null)
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String readData(string persistencePath)
{
FileInputStream fis = null;
BufferedReader br = null;
StringBuilder data = new StringBuilder();
try {
fis = new FileInputStream(persistencePath);
br=new BufferedReader(new InputStreamReader(fis));
String line="";
while ((line=br.readLine())!=null)
data.append(line);
}catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (fis!=null)
fis.close();
if (br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return data.toString();
}
SharedPreferences采用键值对的方式存储多种数据类型的数据。SharedPreferences文件都存储在/data/data/< Package name>/shared_prefs/目录下。
Context类中的getSharedPreferences(文件名,模式)方法
文件名:作为SharedPreferences文件的文件名。
模式:只有MODE_PRIVATE一种表示只有当前应用程序才可以对这个SharedPreferences进行读写。
示例:getSharedPreferences(“data”, MODE_PRIVATE);
Activity类中getPreferences(模式)方法
这个方法默认将当前活动的类名作为SharedPreferences的文件名。
示例: getPreferences(MODE_PRIVATE);
PreferenceManager类下的静态方法getDefaultSharedPreferences方法
这个方法自动使用当前应用程序的包名作为前缀命名SharedPreferences的文件名。
示例: PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);//获取SharedPreferences 对象
SharedPreferences.Editor edit = sharedPreferences.edit();//获取编辑对象
//通过set方法存储各种类型的数据
edit.putString("name","mekeater");
edit.putInt("age",18);
edit.putBoolean("sex",true);
edit.apply();//保存数据到 /data/data/package name/shared_prefs/data.xml文件
SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);//获取SharedPreferences 对象
//通过get方法读取数据
String name = sharedPreferences.getString("name", "");//第二个参数是键不存在的情况下,作为默认值
int age = sharedPreferences.getInt("age", 0);
boolean sex = sharedPreferences.getBoolean("sex", false);
上面讲到的不管是通过流方式将数据存储到文件中,还是说通过SharedPreferences以键值对形式将数据存储到文件中,都只是适合存储简单的数据,不适合逻辑复杂的数据。
术业有专攻,数据库就是设计来存储具有复杂关系的数据的,那么如果要存储具有复杂关系的数据,我们应该采用数据库进行存储,而Android系统提供一个轻量级的SQLite数据库,用于存储复杂的数据。
SQLite提供了一个SQLiteOpenHelper帮助类,通过该类可以非常简单的对数据库进行创建和升级等,但该类是一个抽象类,因此我们首先需要创建一个自己的帮助类去继承它。
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context mContext;
//创建Book表的SQL语句
public static final String CREATE_BOOK_TABLE="create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
//删除Book表的SQL语句
public static final String DROP_BOOK="drop table if exists Book";
//创建Category表的SQL语句
public static final String CREATE_CATEGORY_TABLE="create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)";
//删除Category表的SQL语句
public static final String DROP_CATEGORY="drop table if exists Category";
public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
this.mContext=context;
}
//数据库不存在的前提下,创建数据库完成后会调用该方法
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_BOOK_TABLE);//执行SQL语句,创建Book表
sqLiteDatabase.execSQL(CREATE_CATEGORY_TABLE);//执行SQL语句,创建Category表
}
//数据库版本发生变化的时候,创建数据库操作后,会调用该方法
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL(DROP_BOOK);//执行SQL语句,删除Book表
sqLiteDatabase.execSQL(DROP_CATEGORY);//执行SQL语句,删除Category表
onCreate(sqLiteDatabase);
}
}
//参数1:context 参数2:数据库名 参数3:一般为null 参数4:数据库版本号
MyDatabaseHelper dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,1);
//调用getWritableDatabase方法或者getReadableDatabase方法创建数据库(若数据不存在则创建,若已存着则直接获得已有数据库)
SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
核心示例代码如下:
SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
//以键值对存储数据
ContentValues contentValues = new ContentValues();
contentValues.put("name","我是如何成功的?");
contentValues.put("author","mekeater");
contentValues.put("pages",666);
contentValues.put("price",99);
//将键值对数据存储到Book表中
writableDatabase.insert("Book",null,contentValues);
核心示例代码如下:
SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("price",16);
//参数1:表名 参数2:键值对值 参数3:where语句 参数4 where语句中需要的参数值
writableDatabase.update("Book",contentValues,"author = ?",new String[]{"sun"});
核心示例代码如下:
SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
//参数1:表名 参数2:where语句 参数3 where语句中需要的参数值
writableDatabase.delete("Book",null,null);
核心示例代码如下:
SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
Cursor cursor = writableDatabase.query("Book", null, null, null, null, null, null);
//Cursor cursor = writableDatabase.rawQuery("select * from Book", null);//不采用Sqlite提供的方法,直接采用SQL完成操作
if (cursor.moveToFirst())
{
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d(TAG, "==============="+name+" "+author+" "+pages+" "+price+"===============");
}while (cursor.moveToNext());
}
query方法包含7个参数,各个参数的意义如下表所示:
SQLiteDatabase类提供了execSQL方法直接执行SQL语句,也提供了rawQuery方法直接执行SQL查询语句。
示例代码如下:
db.execSQL ( "insert into Book (name,author,pages,price) values(?,?,?,?)",new String[] { "The Da Vinci Code","Dan Brown","454","16.96"});
通过SQLite数据库提供的方法结合SQL语句,我们就能完成对数据的管理及操作,但是SQL语句一般比较复杂,麻烦,影响开发效率,那么有没有不使用SQL语句就能操作SQLite数据库的方法呢?
有的!
本节学习的LitePal开源库采用对象关系映射(ORM)模式实现将我们开发中常用的一些功能进行封装,使得我们可以不用编写SQL语句就可以完成建表及增删改查的操作。
什么是对象关系映射呢?简单点说,我们使用的编程语言是面向对象语言,而使用的数据库则是关系型数据库,那么将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射了。
下面来应用一下你就懂了。
链接:https://pan.baidu.com/s/1QKpEFUtJ7-d9lgzWiBWIQg?pwd=agjx
提取码:agjx
示例配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
<dbname value="BookStore"/> <!--数据库名-->
<version value="2"/> <!--数据库版本-->
<list>
<mapping class="com.xiaomi.litepaltest.Book"/> <!--映射的表对象类-->
</list>
</litepal>
如在在数据库中创建一张Book表,只需要定义一个Book类,然后在litepal.xml文件的< list>标签内添加这个类即可。如果要对这张表进行CRUD,则还需要这个类继承DataSupport,如创建一个可以进行CRUD的Book表,定义Book类如下:
import org.litepal.crud.DataSupport;
public class Book extends DataSupport {
private int id;
private String author;
private double price;
private int pages;
private String name;
private String press;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
}
只需要进行任意一次数据库操作就完成了数据库的创建,如下示例代码是最简单的一次数据库操作,它就完成了数据库的创建。
Connector.getDatabase();//创建数据库
升级数据库,只需要在litepal.xml文件中修改版本号即可。
如为Book表添加数据,只需要创建Book对象,然后调用DataSupport的save方法即可,核心示例代码如下:
Book book = new Book();
book.setAuthor("mekeater");
book.setName("人性的弱点解读");
book.setPages(666);
book.setPrice(99);
book.setPress("Unknow");
book.save();
核心示例代码如下:
Book book = new Book();
book.setPrice(99.99);
book.updateAll("author = ?","mekeater");
核心示例代码如下:
DataSupport.deleteAll(Book.class,"price < ?","99.99");
核心示例代码如下:
StringBuilder sb = new StringBuilder();
List<Book> books = DataSupport.findAll(Book.class);
for (Book book : books) {
String name = book.getName();
String author = book.getAuthor();
double price = book.getPrice();
String press = book.getPress();
sb.append(name+" "+author+" "+pages+" "+price+" "+press+"\r\n");
}
链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
提取码:n5ag