安卓开发主要使用的存储方式有三种:
文件存储
数据库存储
网络存储
一般轻量级存储,我们使用文件存储就够用了,但是一旦涉及大量存储数据时候,文件存储就显得很笨重了,这个时候就需要我们使用数据库存储了,android系统是自带 SQLite轻量级嵌入式数据库引擎,并提供了相应的调用api,但是书写复杂,大多数开发者都会选择封装后再使用,或者挑选一个开源库来使用。目前主流的的数据库有:
LitePal 郭霖大神出品的一款开源的orm数据库
afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框架,使其更加简单易用。FinalDB模块,android中的orm框架,一行代码就可以进行增删改查。支持一对多,多对一等查询。
ORMLite(Object Relational Mapping Lite)提供了一些轻量级持久化Java对象到SQL数据库,同时也避免了复杂性和更多的标准的ORM包的开销功能。它支持的SQL数据库使用JDBC的数量,还支持原生的Android操作系统数据库API调用sqlite
SugarORM 是对象关系映射模式。不用写复杂的sql语句,而用简单的API即可完成创建和操纵数据;可以在原有的Bean上仅仅添加小的修改而复用Bean;简化而明了的数据库设计和创建过程,同时提供表的一对多的支持。
Realm 是用来替代sqlite的一种解决方案,它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,自动数据同步,简单身份验证,访问控制,事件处理,最重要的是跨平台,目前已有Java,Objective C,Swift,React-Native,Xamarin这五种实现。
LiteOrm 和 DBFlow等
本文主要讲解greenDAO 3.0 GreenDao是为Android设计的对象关系映射(ORM)工具。它提供了对象到关系型数据库SQLite的相应接口。为了在Android工程中使用greenDao,需要创建另一个“生成器”工程,它的任务是在你的工程域里生成具体的代码。因此相比与其它ORM框架具有出众性能。
基本用法
第一步,在根目录(最外层)下的 build.gradle内添加 greenDao 插件
// In your root build.gradle file:
buildscript {
repositories {
jcenter()
mavenCentral() // add repository
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.1' //这个是当前用的 gradle 版本
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
}
第二步,在工程目录下的 build.gradle 内添加相关依赖
// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
dependencies {
implementation 'org.greenrobot:greendao:3.2.2' // add library compile 在新版gradle里已经不建议使用了
}
第三步 指定greenDao 自动生成代码的目录,在工程目录下的 build.gradle 添加如下
greendao {
schemaVersion 1 //指定数据库schema版本号,迁移等操作会用到
daoPackage 'xxx.xx.xxx.greendao'//通过gradle插件生成的数据库相关文件 xxx.xxx.xx 一般填写包名
targetGenDir 'src/main/java' //自定义生成数据库文件的目录
}
第三步 编写自己所需要的实体类 对实体类加一些注解 此处以我写的代码分析一哈
@Entity //这个注解必须要 告诉greenDao这是一个实体类
public class TokenEntity implements Serializable {
static final long serialVersionUID = -15515456L;
@Id //标识为id 可选 还有大量注解 可查询官方文档
private String id;
private String address;
private String name;
private String tag;
private String tokenAddress;
private double balance;
一些常用注解
@Entity 用于标识这是一个需要Greendao帮我们生成代码的bean
@Id 标明主键,括号里可以指定是否自增
@Property 用于设置属性在数据库中的列名(默认不写就是保持一致)
@NotNull 非空
@Transient 标识这个字段是自定义的不会创建到数据库表里
@Unique 添加唯一约束
第四步,自动生成代码,点击make project greenDAO插件 会帮我们生成一些文件。
首先实体类的变化,构造方法和set,get方法都自动生成
@Entity
public class TokenEntity implements Serializable {
static final long serialVersionUID = -15515456L;
@Id
private String id;
private String address;
private String name;
private String tag;
private String tokenAddress;
private double balance;
private long decimals; //精度
@Generated(hash = 194050609)
public TokenEntity(String id, String address, String name, String tag,
String tokenAddress, double balance, long decimals) {
this.id = id;
this.address = address;
this.name = name;
this.tag = tag;
this.tokenAddress = tokenAddress;
this.balance = balance;
this.decimals = decimals;
}
....
项目里src下也会新增相关类,DaoMaster,DaoSession和实体类的Dao
不封装基本使用,非常不建议
//DB_NAME 自己定义的数据库名字
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(RuntimeContext.getApplication(),DB_NAME,null);
mDaoMaster = new DaoMaster(devOpenHelper.getWritableDb());
mDaoSession = mDaoMaster.newSession();
mDaoSession.getTokenEntityDao().insert(new TokenEntity()); //获取实体类的entityDao api 提供增删改查
简单封装
DBManager.class 单例模式 获取数据库的 master 和session
/**
* 数据库管理类
*/
public class DBManager {
final static String DB_NAME = "xxx_db";
private static DBManager mInstance;
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;
private DBManager(){
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(RuntimeContext.getApplication(),DB_NAME,null);
mDaoMaster = new DaoMaster(devOpenHelper.getWritableDb());
mDaoSession = mDaoMaster.newSession();
}
public DaoMaster getDaoMaster() {
return mDaoMaster;
}
public DaoSession getDaoSession() {
return mDaoSession;
}
public static DBManager getInstance(){
if(mInstance==null){
synchronized (DBManager.class){
if(mInstance==null){
mInstance = new DBManager();
}
}
}
return mInstance;
}
}
针对每个实体类编写工具类,后期替换别的数据库,或者改动会方便很多,此处以我写的token实体编写增删改查工具类,本来想通过反射写一个通用的增删改成类,结果发现查的时候每个表的属性都不一样就放弃。
/**
* 负责token 表的增删改查
*/
public class TokenDbUtil {
public static boolean insert(TokenEntity entity){
try {
DBManager.getInstance().getDaoSession().getTokenEntityDao().insert(entity);
}catch (Exception e){
return false;
}
return true;
}
public static boolean insertOrReplace(TokenEntity entity){
try {
DBManager.getInstance().getDaoSession().getTokenEntityDao().insertOrReplace(entity);
}catch (Exception e){
return false;
}
return true;
}
/**
* 批量插入
* @param list
* @return
*/
public static boolean insertBatch(List list){
try {
DBManager.getInstance().getDaoSession().getTokenEntityDao().insertInTx(list);
}catch (Exception e){
return false;
}
return true;
}
public static boolean update(TokenEntity entity){
try {
DBManager.getInstance().getDaoSession().getTokenEntityDao().update(entity);
}catch (Exception e){
return false;
}
return true;
}
/**
* 通过地址查询 该address下拥有的token
* @param address
* @return
*/
public static List queryByAddress(String address){
List list = null;
list =DBManager.getInstance().getDaoSession().getTokenEntityDao()
.queryBuilder()
.where(TokenEntityDao.Properties.Address.eq(address)).build().list();
return list;
}
public static boolean delete(TokenEntity entity){
try {
DBManager.getInstance().getDaoSession().getTokenEntityDao().delete(entity);
}catch (Exception e){
return false;
}
return true;
}
}
greenDAO 基本使用方法就写到这里了。
greenDAO 开发中遇到的一些小坑
1.开发中突然想加一些实体类属性,发现在跑App时报各种错,删掉App重新装,因为新增属性,会改变表结构,而又没有更新build.gradle 里版本号, 数据库就会出错。
2.实体类序列化,一开始没想到该实体类需要序列化,再加上 implements Serializable 代码时候出各种错,删掉代码里的@Generated(hash = xxxxx) 重新 make project
- 各种打印java.lang.ClassNotFoundException: Didn’t find class “net.sqlcipher.database.SQLiteOpenHelper
的log , 虽然不影响使用,但是还是很烦,因为greenDAO 用到加密相关的东西,而这个库没有被加入,在build.gradle 里加入
implementation 'net.zetetic:android-database-sqlcipher:3.4.0@aar'
就不报这个异常了。这里又有一个坑,官方文档给的 https://www.zetetic.net/sqlcipher/sqlcipher-for-android/
版本可能不存在,当初按官网文档走,怎么都下载不下来。由于多加了一个库,App体积也变大了不少,如果没有用到加密库,那就不用加这个库了。看到这里了,点个赞呗。