RxAndroid:Observable.first()返回null对象的List

时间:2016-06-26 20:59:23

标签: android rx-android

tutorial之后,我创建了两个用于获取数据的源。我希望如果本地没有数据,我会发送网络请求。但是所有的时间都从本地源获取空对象列表(这是Observable.concat中的第一个)。

对于使用SQLite和SQLBrite包装器的本地源以及用于远程源的Retrofit:

@Override
public Observable<Item> get(String id) {
    //creating sql query

    return databaseHelper.createQuery(ItemEntry.TABLE_NAME, sqlQuery, id)
        .mapToOneOrDefault(mapperFunction, null);
}

存储库中有用于查找可观察对象的方法:

@Override
public Observable<Item> get(String id) {
    Observable<Item> local = localDataSource
        .get(id)
        .doOnNext(new Action1<Item>() {
            @Override
            public void call(final Item item) {
                // put item to cache
            }
        });
    Observable<Item> remote = remoteDataSource
        .get(id)
        .doOnNext(new Action1<Item>() {
            @Override
            public void call(final Item item) {
                // save item to database and put to cache
            }
        });
    return Observable.concat(local, remote).first();
}

为了获取ID列表,我正在使用下一个方法:

@Override
public Observable<List<Item>> getList(final List<String> ids) {
    return Observable
        .from(ids)
        .flatMap(new Func1<String, Observable<Item>>() {
            @Override
            public Observable<Item> call(String id) {
                return get(id);
            }
        }).toList();
}

并在片段中订阅:

Subscription subscription = repository
    .getList(ids)
    .flatMap(new Func1<List<Item>, Observable<Item>>() {
        @Override
        public Observable<Item> call(List<Item> result) {
            return Observable.from(result);
        }
    })
    .toList()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<List<Item>>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(List<Item> result) {
            // there get list of null objects
        }
}); 

因此,主要目标是首先检查本地存储,如果没有项目 - 向服务器发出请求。但是现在如果item不存在,我得到null而不是发送请求。

有人可以帮我理解原因吗?

2 个答案:

答案 0 :(得分:1)

在concat之后调用first()当然会返回第一个项目,无论它是否有效。 Yout first()函数应该验证该值,并且只提交有效的&#39;第一项。

类似的东西:

public void test() {
    Integer[] ids = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    Observable.from(ids)
            .flatMap(new Func1<Integer, Observable<String>>() {
                @Override
                public Observable<String> call(Integer id) {
                    return get(id);
                }
            })
            .toList()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<List<String>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(List<String> strings) {

                }
            });
}

public Observable<String> get(int id) {
    return Observable.concat(getLocal(id), getRemote(id))
            .first(new Func1<String, Boolean>() {
                @Override
                public Boolean call(String s) {
                    return s != null;
                }
            });
}

public Observable<String> getLocal(int id) {
    return Observable.just(id < 5 ? "fromLocal id:"+id : null);
}

public Observable<String> getRemote(int id) {
    return Observable.just(id >= 5 ? "fromRemote id:"+id : null);
}

将结果带来:

fromLocal id:1
fromLocal id:2
fromLocal id:3
fromLocal id:4
fromRemote id:5
fromRemote id:6
fromRemote id:7
fromRemote id:8
fromRemote id:9
fromRemote id:10

答案 1 :(得分:1)

来自github的

Answer

  

你的函数Observable get()返回无穷的Observable因为   mapToOneOrDefault没有自己完成Observable并做出反应   db的更新。您需要限制此Observable的发射,因为   operator concat等待onCompleted事件。

例如,它应该如下所示:

return Observable.concat(localSource.first(), remoteSource)
    .filter(new Func1<Item, Boolean>() {
        @Override
        public Boolean call(Item item) {
            return item!= null;
        }
    });