RxJava + Retrofit + Realm正在进行无限制的get请求

时间:2017-07-17 04:54:04

标签: java android realm retrofit

我对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()));
                }
            });
}

非常感谢你。

2 个答案:

答案 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>