Realm(Java)数据库使用文档(第三方类库)


Realm(Java)数据库使用文档(目录)

本节介绍如何将Realm与其他常用的Android库集成。

14.1 GSON

GSON是Google创建的用于反序列化和序列化JSON的库。GSON应该与Realm开箱即用。

// Using the User class
public class User extends RealmObject {
    private String name;
    private String email;
    // getters and setters left out ...
}

Gson gson = new GsonBuilder().create();
String json = "{ name : 'John', email : '[email protected]' }";
User user = gson.fromJson(json, User.class);

您还可以在我们的GridViewExample中看到GSON如何与Realm一起工作的示例

14.2 序列化Serialization

为了与诸如Retrofit之类的库完全兼容,您通常会希望能够同时反序列化和序列化对象。将Realm对象序列化为JSON不适用于GSON的默认行为,因为GSON将使用字段值而不是getter和setter

要使GSON序列化与Realm一起使用,您需要为每个可以序列化的对象编写一个自定义JsonSerializer(连接已失效),并将其注册为TypeAdapter(连接已失效)

本要点说明了如何实现。

14.3 原始清单Primitive lists

尽管Realm在本地支持将JSON中的数组导入到原语列表,但是缺少对原语列表的查询支持仍然可能是一个问题。您可能希望将基本类型的JSON数组作为RealmObject的列表导入。如果无法更改JSON API,则可以编写GSON的自定义TypeAdapter(连接已失效),该适配器自动在JSON的原始类型和Realm使用的包装对象之间进行映射。

本要点中,是一个为Integer使用包装对象的示例,但是该模板可以用于具有Realm支持的数据类型的所有基本数组。

14.4 故障排除Troubleshooting

Realm对象可以包含内部包含循环引用的字段。发生这种情况时,GSON可能会抛出StackOverflowError。我们已经看到,当Realm对象具有Drawable字段时,会发生这种情况:

public class Person extends RealmObject {
    @Ignore
    Drawable avatar;
    // other fields, etc
}

上面的Person类包含一个应用了@Ignore批注的Android Drawable。在GSON序列化期间,正在检查Drawable并导致StackOverflowError(GitHub问题)。为了减轻这种情况,请将以下代码添加到shouldSkipField方法中。

public boolean shouldSkipField(FieldAttributes f) {
  return f.getDeclaringClass().equals(RealmObject.class) || f.getDeclaringClass().equals(Drawable.class);
}

请注意Drawable.class评估。这告诉GSON在序列化期间跳过此字段。添加此选项将缓解StackOverflowError。

14.5 Jackson 数据绑定

Jackson Databind是用于将JSON数据绑定到Java类的库。

Jackson使用反射来执行数据绑定。这与Realm对RxJava的支持相冲突,因为RxJava可能无法用于类加载器。这可能会导致如下所示的异常:

java.lang.NoClassDefFoundError: rx.Observable
at libcore.reflect.InternalNames.getClass(InternalNames.java:55)
...

可以通过将RxJava添加到您的项目或创建两个类似于以下内容的空虚拟文件来解决此问题。

// File 1
package io.reactivex;

public class Flowable {
}


// File 2
package io.reactivex;

public class Observable {
}

// File 3
package io.reactivex;

enum BackpressureStrategy {
    LATEST;
}

此问题也已报告给此处的Jackson项目。

14.6 Kotlin

Realm与Kotlin编程语言完全兼容。请参阅Kotlin指南

14.7 Parceler

Parceler是一个库,可自动生成使对象遵守Parcelable接口所需的样板。由于Realm使用代理类,因此Parceler需要以下设置才能与Realm的模型类一起使用。

Realm中的代理类使用模型类的全限定名称加上RealmProxy后缀,因此例如io.realm.model.Person成为io_realm_model_PersonRealmProxy.class

// 所有扩展RealmObject的类都将具有一个由注释处理器创建的匹配的RealmProxy类。必须使包裹程序知道此类。请注意,只有在项目至少编译一次之后,该类才可用。
@Parcel(implementations = { some_package_PersonRealmProxy.class },
        value = Parcel.Serialization.BEAN,
        analyze = { Person.class })
public class Person extends RealmObject {
    // ...
}

如果您使用Gradle获取Parceler,请确保存在以下几行(有关更多详细信息,请参见此处):

compile "org.parceler:parceler-api:1.0.3"
apt "org.parceler:parceler:1.0.3"

使用Parceler时要注意一些重要限制:

  1. 如果您的模型包含RealmList,则需要注册一个特殊的适配器
  2. 打包对象后,它就会与Realm分离,此时的行为就像是包含数据快照的非托管对象。对该对象的进一步更改将不会保留在Realm中。

14.8 Retrofit

RetrofitSquare提供的一个库,可以轻松以类型安全的方式使用REST API。

Realm可以同时使用Retrofit 1. *和2. *,但是请注意Retrofit不会自动将对象添加到Realm,而是必须使用realm.copyToRealm()realm.copyToRealmOrUpdate()方法手动添加它们。

GitHubService service = restAdapter.create(GitHubService.class);
List<Repo> repos = service.listRepos("octocat");

// 将元素从Retrofit复制到Realm以保留它们。
realm.beginTransaction();
List<Repo> realmRepos = realm.copyToRealmOrUpdate(repos);
realm.commitTransaction();

14.9 Robolectric

Robolectric是一个库,可让您直接在JVM中而不是在电话或仿真器中运行JUnit测试。当前,Robolectrics不支持与Realm捆绑在一起的本机库。这意味着目前尚无法使用Robolectric测试Realm。

您可以在此处关注功能请求:https://github.com/robolectric/robolectric/issues/1389

14.10 RxJava

RxJava是Netflix的一个Reactive Extensions库,它扩展了Observer模式。这样就可以观察到数据变化的可组合序列。

Realm对RxJava 2 Flowable和Observable具有一流的支持

//结合Realm、Retrofit和RxJava(为简洁起见,使用Retrolambda语法)
//加载所有人并将其与来自GitHub的最新统计信息合并(如果有的话)
Realm realm = Realm.getDefaultInstance();
GitHubService api = retrofit.create(GitHubService.class);
realm.where(Person.class).isNotNull("username").findAllAsync().asFlowable()
    .filter(persons.isLoaded)
    .flatMap(persons -> Observable.from(persons))
    .flatMap(person -> api.user(person.getGithubUserName())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(user -> showUser(user));

异步查询是非阻塞的-上面的代码将立即返回RealmResults实例。如果要确保仅对加载的列表进行操作,请通过过滤器运算符过滤Flowable,然后通过调用[RealmResults.isLoaded](api/io/realm/RealmResults.html#isLoaded–)方法检查列表。通过检查“RealmResults”是否已加载,可以确定查询是否已完成。

Realm 7.0版中的新功能:所有Realm Observable和Flowables都返回冻结的对象。这意味着这些对象是不可变的,但是可以从任何线程或调度程序读取和查询,而不必担心会遇到IllegalStateException:来自错误线程的realm访问。

有关更多示例,请参见RxJava示例项目

RxJava是一个可选的依赖项,这意味着Realm不会自动包含它。这样的好处是您可以选择使用哪个版本的RxJava,并且避免在不使用RxJava的项目中方法计数过大。必须将RxJava手动添加到build.gradle文件中。

dependencies {
  compile 'io.reactivex:rxjava:2.1.4'
}

通过创建自定义RxObservableFactory,可以配置Realm如何创建流。使用RealmConfiguration进行配置。

RealmConfiguration config = new RealmConfiguration.Builder()
  .rxFactory(new MyRxFactory())
  .build()

如果未定义RxObservableFactory,则Realm默认为RealmObservableFactory,这是Realm提供的支持RxJava <= 2. *的类。 从Realm版本7.0.0开始,可以将此类配置为返回活动或冻结对象。 默认值为冻结对象。

// 禁用可观察对象的冻结对象
RealmConfiguration config = new RealmConfiguration.Builder()
  .rxFactory(new RealmObservableFactory(false)) 
  .build()

如果您使用的是RxJava 1,则可以使用David Karnok的该库在RxJava 2和RxJava 1类型之间进行转换。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章