2018.03.31、Android-ObjectBox-监听

数据监听和RX(Data Observers and Reactive Extensions)

通过以下方式,ObjectBox可以让您的应用轻松应对数据变更:

  • 数据监听(data observers)
  • Reactive extensions
  • Rxjava的适配库

数据监听

第一个例子:

//第一条语句创建一个常规查询来获取未完成的 Task 对象。
Query<Task> query = taskBox.query()
                            .equal(Task_.complete,false)
                            .build();
                           
// 第二条将观察者连接到查询。                           
query.subscribe(subscriptions)
     .on(AndroidScheduler.mainThread())
     .observer(data -> updateUi(data));
     
复制代码
  • 查询在后台执行
  • 一旦查询完成,观察者获得结果数据
  • 以后未完成对象如果有更改时 ,查询将再次执行
  • 一旦查询结果有变化,它们被传递给观察者
  • 观察者在Android的主线程上被调用

subscribe(subscriptions):这是一个所有订阅的集合,如果你想要停止观察,可以调用cancel()来取消。

Data Observers Basics

当对象改变时,ObjectBox通知订阅的数据观察者。观察者可以订阅某些对象类型的更改(通过BoxStore)或查询结果。

首先,要创建数据观察者,您需要实现io.objectbox.reactive.DataObserver接口:

public interface DataObserver<T> {
    void onData(T data);
}
复制代码

这个观察者在两种情况下被ObjectBox调用:

  • 订阅之后
  • 数据变更

onData() 被异步线程调用,并且线程解耦(调用线程不是 引起数据变化的线程,比如:不是提交修改事务的线程,请记住)

观察全部变化

BoxStore允许 DataObserver 订阅对象类型。假设您想观察 待办事项列表应用的Task 对象:

DataObserver<Class> taskObserver = ...;
boxStore.subscribe(Task.class).observer(taskObserver);
复制代码

数据库中Task Box有任何改变则会调用taskObserver 。 注意:还有 不带任何参数的subscribe()。它订阅观察者以接收所有可用对象类的更改。

观察查询

ObjectBox让你建立查询 来找到符合特定条件的对象。
查询是ObjectBox的重要组成部分:只要您需要特定的一组数据,您就需要使用查询。

将查询和观察者结合在一起会产生一个方便而强大的工具:当相关数据发生变化时,查询观察者将自动提供新的结果。假设您在应用中显示待办任务列表。您可以使用 DataObserver 获取尚未完成的所有任务,并将其传递给方法 updateUi ()(请注意,我们在此使用lambda语法):

Query query = taskBox.query().equal(Task_.completed, false).build(); subscription = query.subscribe().observer(data -> updateUi(data));

那么我们的观察者什么时候被调用?观察者订阅时,查询将在一个单独的线程中运行。一旦查询结束,它将被传递给观察者。这是对观察者的第一次调用。

请注意,这种模式可以大大简化您的代码:您的数据有一个地方用来更新您的用户界面。没有单独的初始化代码,没有重发的事件,没有重建的查询等。

取消订阅

observer()方法会返回 io.objectbox.reactive.DataSubscription接口的实现:

public interface DataSubscription {
    void cancel();
    boolean isCanceled();
}
复制代码

所以,如果你打算取消观察,可以保存DataSubscription,调用 cancel() 让ObjectBox去掉该观察者:

DataSubscription subscription = boxStore.subscribe().observer(myObserver);

// At some later point:
subscription.cancel();
复制代码

由于您可能有多个查询订阅,我们推荐使用 DataSubscriptionList 来保存多个 DataSubscription 对象。基本模式是这样的:

private DataSubscriptionList subscriptions = new DataSubscriptionList();

protected void onStart() {
  super.onStart();
  Query<X> query = box.query()... .build();
  query.subscribe(subscriptions)... .observe(...);
}

protected void onStop() {
  super.onStop();
  subscriptions.cancel();
}
复制代码

注意:在Android上,您通常会在onCreate()/ onStart()/ onResume()生命周期方法之一中创建订阅,并在其对应的onDestroy()/ onStop()/ onPause()中取消 订阅 。

观察者和事务

观察者通知发生在事务提交后。对于某些场景,了解事务边界尤为重要。如果调用put 或 remove,隐式事务被启动并提交。
例如,这段代码会触发两次User上的数据观察者:

box.put(friendUser);
box.put(myUser);
复制代码

有几种方法可以将多个操作组合到一个事务中,例如使用 BoxStore类中的 runInTx() 或 callInTx()方法之一。对于我们的简单例子,我们可以简单地使用put()接受多个对象的重载方法:

box.put(friendUser, myUser);
复制代码

这只会产生一个事务,从而发出一个 DataObserver 通知。

Reactive Extensions(RX)

ObjectBox为大多数功能提供了简单和方便的RX。虽然其中大部分是受RxJava的启发,但实际上并不是基于RxJava。ObjectBox带来了自己的特性,因为并不是所有的开发人员都熟悉RxJava(对于RxJava ObjectBox库见下文)。我们不想强加RxJava(〜10k方法)的复杂性(Rx几乎就像学习一种新的语言)和大小。所以,让我们现在保持简单和整洁。

线程切换

ObjectBox允许将观察者从后台线程切换到主线程。我们来看看上面的待办任务示例的修订版本:

Query<Task> query = taskBox.query().equal(Task_.complete, false).build();
query.subscribe().on(AndroidScheduler.mainThread())
                .observer(data -> updateUi(data));
复制代码

on()方法是告诉ObjectBox我们的观察者被调用的线程。 AndroidScheduler.mainThread () 是一个内置的调度器实现。您可以 使用自定义 Looper创建 AndroidScheduler,或者实现io.objectbox.reactive.Scheduler接口来自定义一个线程切换。

数据变换

也许你想在将数据交给观察者之前进行数据转换。比方说,你想跟踪每种类型的所有存储对象的总数。BoxStore subscription 返回Class信息,这个例子展示了如何将它们转化为实际的总数:

boxStore.subscribe()
    .transform(clazz -> return boxStore.boxFor(clazz).count())
    .observer(count -> updateCount(count));
复制代码

这段transform代码将class信息变换为总数,所以DataObserver 在onData()中将接受 Long作为参数 。

这段transform代码将class信息变换为总数,所以DataObserver 在onData()中将接受 Long作为参数 。

虽然lambda语法非常简洁,但我们还是来看一下io.objectbox.reactive.Transformer接口:

public interface DataTransformer<FROM, TO> {
    TO transform(FROM source) throws Exception;
}
复制代码
  • 实际上类型可以不变。从技术上讲,可以在Transformer中处理一些数据然后发出去,(私货:例如过滤等等)
  • Transformer是异步执行。可以执行一些耗时操作。
异常

也许你注意到变换实现可能会抛出任何类型的异常。此外, DataObserver 可能会引发 RuntimeException。在这两种情况下,您都可以实现 ErrorObserver :io.objectbox.reactive.ErrorObserver 以收到异常:

public interface ErrorObserver {
    void onError(Throwable th);
}
复制代码

在subscribe()之后调用它们,实现方式如下:

query.subscribe().onError(new ErrorObserver() {
                    @Override
                    public void onError(Throwable th) {

                    }
                }).observer(...)
复制代码
线程概述

如前所说,线程总结如下:

  • 查询执行在后台线程上运行(仅限于此任务)
  • DataTransformer 在后台线程上运行(仅限于此任务)
  • 除非通过 on()方法指定线程,否则 DataObserver 和 ErrorObserver都将在后台线程上运行 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值