我对rxJava完全不熟悉,而且我真的很困惑,我想让我的应用程序首先脱机并且我决定使用Realm和Retrofit,首先我想从改造中获取数据然后从我的远程Web服务获取数据然后,使用领域insertOrUpdate
将远程对象与本地对象合并。到目前为止,我能够开始这个过程,但是当我在stetho上查看我的网络请求时,此方法已完成请求无限次。我哪里做错了?这是函数
public Observable<RealmResults<Event>> all() {
Realm realm = Realm.getDefaultInstance();
return realm.where(Event.class).findAllAsync()
.asObservable()
.filter(new Func1<RealmResults<Event>, Boolean>() {
@Override
public Boolean call(RealmResults<Event> events) {
return events.isLoaded();
}
})
.doOnNext(new Action1<RealmResults<Event>>() {
@Override
public void call(RealmResults<Event> events) {
service.getEvents()
.subscribeOn(Schedulers.io())
.subscribe(new Action1<List<Event>>() {
@Override
public void call(final List<Event> events) {
try(Realm realm = Realm.getDefaultInstance()) {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(events);
}
});
} // auto-close
}
});
}
});
}
这里是我活动的功能,我在哪里使用它
private void getEvents() {
Log.i("EVENTSELECTION", "STARTING");
repository.all()
.subscribe(new Subscriber<List<Event>>() {
@Override
public void onCompleted() {
Log.i("EVENTSELECTION", "Task Completed");
swipeRefreshLayout.setRefreshing(false);
}
@Override
public void onError(Throwable e) {
Log.e("EVENTSELECTION", e.getMessage());
swipeRefreshLayout.setRefreshing(false);
e.printStackTrace();
}
@Override
public void onNext(List<Event> events) {
Log.i("EVENTSELECTION", String.valueOf(events.size()));
}
});
}
非常感谢你。
答案 0 :(得分:2)
我哪里出错了?
让我们来看看:
1
public Observable<RealmResults<Event>> all() {
Realm realm = Realm.getDefaultInstance();
这会打开永远不会关闭的Realm实例。因此,您的Realm生命周期管理是错误的,请参阅documentation for best practices。
2
return realm.where(Event.class).findAllAsync()
.asObservable() // <-- listens for changes in the Realm
// ...
.doOnNext(new Action1<RealmResults<Event>>() {
@Override
public void call(RealmResults<Event> events) {
service.getEvents() // <-- downloads data
.subscribeOn(Schedulers.io())
.subscribe(new Action1<List<Event>>() {
你基本上说&#34;如果Realm中的数据有任何变化,那么从服务下载数据并将其写入Realm&#34;
这将触发将触发下载的RealmChangeListener等等。
这是一个概念性错误,您错误地使用了Realm notifications。
RealmResults<T>
不仅仅是一个对象列表,它还是一个订阅变更。因此,您需要将其保留为字段引用,并且&#34;保持订阅数据库中的更改&#34;。
RealmResults<Sth> results;
RealmChangeListener<RealmResults<Sth>> changeListener = (element) -> {
if(element.isLoaded()) {
adapter.updateData(element);
}
};
void sth() {
results = realm.where(Sth.class).findAllSortedAsync("id");
results.addChangeListener(changeListener);
}
void unsth() {
if(results != null && results.isValid()) {
results.removeChangeListener(changeListener);
results = null;
}
}
在您的情况下,RealmResults<T>
代表订阅并且还提供对当前/新数据的访问权限,并将其Observable<T>
打包为您可以创建订阅者。
Observable<List<<Sth>> results;
Subscription subscription;
Action1<List<Sth>> changeListener = (element) -> {
if(element.isLoaded()) {
adapter.updateData(element);
}
};
void sth() {
results = realm.where(Sth.class).findAllSortedAsync("id").asObservable();
subscription = results.subscribe(changeListener);
}
void unsth() {
if(subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
subscription = null;
results = null;
}
}
如您所见,您在组件的开头有一个订阅,在组件的末尾有一个取消订阅。
调用Observable.first()
不正确,这样做没有意义。如果您在任何教程中看到它(我之前已经看过它......),那么该教程是错误的。
答案 1 :(得分:0)
所以它在领域真的是by design
并且它不会调用onCompleted,我在.first()
函数的末尾添加了getEvents
以仅获得第一个结果。< / p>