一、我的需求
我希望在我的Android项目中构建一套缓存系统。当我将从服务器上请求到的JSON反序列化为JAVA对象时,我将该对象存入缓存,保存起来。下次假如网络请求失败,我从缓存中读取上一次保存好的对象展现给用户。
写完回来,发现Object Box并解决不了对象持久化存储的问题,因为其不支持内部类。所以这个问题还是得用Serializable来完成。不过,经此一错,我对数据库的理解更加深刻了。
那就是数据库,不管是SQL还是NoSQL,都是用表来存数据的。它存储的对象是一组数据,而不是单一数据。
二、目前的技术解决方案
- Serializable:序列化对象为文件,并保存在文件里
- SharedPreferences:Android官方提供的缓存文件,以XML形式存储
- SQLite:官方数据库
- greenDAO:基于SQLite的轻量级ORM
- Realm:第三方数据库
- Object Box:第三方数据库
首先,我的数据需要有保密性,不能用户直接从手机中能拷出来,故Serializable与SharedPreferences不予考虑。
其次,SQLite要写SQL语句,而我更希望使用NoSQL的特性,故不予考虑。
所以,最后把目光放在了Realm与greenDAO解决方案上。
在知乎上搜,看Realm的BUG有不少,我希望用一个风评比较好的数据库,故Realm也不予考虑。
所以,最后目光看向了greenDAO这个基于SQLite的抽象层上面。
进入官方网站一看,发现该公司推出了一个新的产品叫做Object Box。不知怎的,我也没调研这个坑多不多,但是凭借着黑客的直觉,决定使用该方案作为我的技术解决方案。
三、安装Object Box
gradle:将黑体部分添加至你的项目中
// In your root build.gradle file:
buildscript {
ext.objectboxVersion = '1.2.1'
repositories {
jcenter()
maven { url "http://objectbox.net/beta-repo/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion"
}
}
allprojects {
repositories {
jcenter()
maven { url "http://objectbox.net/beta-repo/" }
}
}
// In your (app) module build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'io.objectbox'
四、创建实体类Bean并编译你的项目
创建一个Bean.java文件,然后在Android Studio中按Ctrl + F9
里面被@Id标注的是一个由ObjectBox维护的自增ID,我们不用手动给其赋值。
@Entity
public class Bean {
@Id
private
long id;
public Bean(String uuid, String token) {
this.uuid = uuid;
this.token = token;
}
private String uuid;
private String token;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
五、创建App.java并在AndroidManifest.xml中配置
public class App extends Application {
public static final String TAG = "ObjectBoxExample";
public static final boolean EXTERNAL_DIR = false;
private BoxStore boxStore;
@Override
public void onCreate() {
super.onCreate();
boxStore = MyObjectBox.builder().androidContext(App.this).build();
if (BuildConfig.DEBUG) {
new AndroidObjectBrowser(boxStore).start(this);
}
}
public BoxStore getBoxStore() {
return boxStore;
}
}
六、获取BeanBox
public class MainActivity extends AppCompatActivity {
private Box<Bean> beanBox;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BoxStore boxStore = ((App) getApplication()).getBoxStore();
beanBox = boxStore.boxFor(Bean.class);
}
}
七、数据库操作:增
//增
private void add(Box<Bean> beanBox) {
Bean bean = new Bean("1234", "fuck");
if (beanBox != null) {
beanBox.put(bean);
}
}
八、数据库操作:查
查操作,ObjectBox提供了很多API,这里只介绍:equal()
本函数操作:找到一组uuid为1234的bean,返回其中的第一个——beanList.get(0)
//查
private Bean query(Box<Bean> beanBox) {
if (beanBox != null) {
List<Bean> beanList = beanBox.query().equal(Bean_.uuid, "1234").build().find();
return beanList.get(0);
}
return null;
}
九、数据库操作:删
删操作,ObjectBox提供了很多API,如上图所示。
用id作为标识删除数据:
private void delete(Box<Bean> beanBox) {
if (beanBox != null) {
beanBox.remove(1);
}
}
通过「查操作」获取「想删除的对象」,再通过「删操作」删除该对象。
//删
private void delete(Box<Bean> beanBox) {
Bean bean = query(beanBox);
if (beanBox != null) {
beanBox.remove(bean);
}
}
十、数据库操作:改
这里也是,先通过「查操作」获取「想改的对象」,然后修改该对象的值,最后调用put()就算是完成了「改」
//改
private void update(Box<Bean> beanBox) {
Bean bean = query(beanBox);
bean.setToken("FUCK YOU");
if (beanBox != null) {
beanBox.put(bean);
}
}
十一、注意:「删」、「改」的函数里,我都调用了「查」——query()
别起急