RxJava 按需加载项目
RxJava Load items on demand
我想在其他一些可观察对象发出新项目(触发器)时加载下一个项目。
这是发出物品的代码:
public Observable<Item> get() {
return idApi.get().flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull List<String> ids) throws Exception {
return Observable.fromIterable(ids);
}
}).flatMap(new Function<String, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final String id) throws Exception {
return dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
}
});
}
触发可观察:
RxView.clicks(view.findViewById(R.id.button_more)).debounce(500, TimeUnit.MILLISECONDS);
我能解决这个问题的唯一方法是使用 Subject
并持有对 id 列表的引用,这不优雅而且似乎没有反应。
编辑: 到目前为止,这是我的解决方案,但我必须直接订阅触发事件。我觉得不优雅。
@Override
public Observable<Item> get(final Observable<Object> trigger) {
final PublishSubject<Item> subject = PublishSubject.create();
return idApi.get().flatMap(new Function<List<String>, ObservableSource<Queue<String>>>() {
@Override
public ObservableSource<Queue<String>> apply(@NonNull List<String> ids) throws Exception {
final Queue<String> q = new LinkedList<>(ids);
return Observable.just(q);
}
}).flatMap(new Function<Queue<String>, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final Queue<String> ids) throws Exception {
trigger.subscribeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (ids.size() > 0) {
final String id = ids.poll();
dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data, id) l
}
}).subscribe(new Consumer<Item>() {
@Override
public void accept(@NonNull Item item) throws Exception {
subject.onNext(item);
}
});
} else {
subject.onComplete();
}
}
});
return subject;
}
});
}
使用 zip
public Observable<Item> get(View v) {
return idApi.get().flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull List<String> ids) throws Exception {
return Observable.fromIterable(ids);
}
}).zipWith(RxView.clicks(v).debounce(500, TimeUnit.MILLISECONDS), (n, i) -> n))
.flatMap(new Function<String, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final String id) throws Exception {
return dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
}
});
}
每次点击获得 N 项
public Observable<Item> getN(View v, int nitems) {
return idApi.get().flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull List<String> ids) throws Exception {
return Observable.fromIterable(ids);
}
}).buffer(nitems).zipWith(RxView.clicks(v).debounce(500, TimeUnit.MILLISECONDS), (n, i) -> n))
.flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull final List<String> ids) throws Exception {
return Observable.from(ids)
}
}
)
.flatMap(new Function<String, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final String id) throws Exception {
return dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
}
}
});
}
编辑:您仍然需要使用 subscribeOn 来确保您在 RXView.clicks 的主线程上和任何网络的 IO 线程上。
不太好,但它有效:
你的获取方法:
Observable<Item> get(final String id){
return Observable.defer(() -> {
dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
})
}
您的点击次数:
private List<String> ids = {//your id s}
private int current = 0;
RxView.clicks(view).flatmap(ignore -> get(ids.get(current++)))
.subscribe(//your Observer)
我想用 zipwith()
推荐那个答案,看起来比我的答案好。
我想在其他一些可观察对象发出新项目(触发器)时加载下一个项目。
这是发出物品的代码:
public Observable<Item> get() {
return idApi.get().flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull List<String> ids) throws Exception {
return Observable.fromIterable(ids);
}
}).flatMap(new Function<String, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final String id) throws Exception {
return dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
}
});
}
触发可观察:
RxView.clicks(view.findViewById(R.id.button_more)).debounce(500, TimeUnit.MILLISECONDS);
我能解决这个问题的唯一方法是使用 Subject
并持有对 id 列表的引用,这不优雅而且似乎没有反应。
编辑: 到目前为止,这是我的解决方案,但我必须直接订阅触发事件。我觉得不优雅。
@Override
public Observable<Item> get(final Observable<Object> trigger) {
final PublishSubject<Item> subject = PublishSubject.create();
return idApi.get().flatMap(new Function<List<String>, ObservableSource<Queue<String>>>() {
@Override
public ObservableSource<Queue<String>> apply(@NonNull List<String> ids) throws Exception {
final Queue<String> q = new LinkedList<>(ids);
return Observable.just(q);
}
}).flatMap(new Function<Queue<String>, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final Queue<String> ids) throws Exception {
trigger.subscribeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (ids.size() > 0) {
final String id = ids.poll();
dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data, id) l
}
}).subscribe(new Consumer<Item>() {
@Override
public void accept(@NonNull Item item) throws Exception {
subject.onNext(item);
}
});
} else {
subject.onComplete();
}
}
});
return subject;
}
});
}
使用 zip
public Observable<Item> get(View v) {
return idApi.get().flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull List<String> ids) throws Exception {
return Observable.fromIterable(ids);
}
}).zipWith(RxView.clicks(v).debounce(500, TimeUnit.MILLISECONDS), (n, i) -> n))
.flatMap(new Function<String, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final String id) throws Exception {
return dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
}
});
}
每次点击获得 N 项
public Observable<Item> getN(View v, int nitems) {
return idApi.get().flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull List<String> ids) throws Exception {
return Observable.fromIterable(ids);
}
}).buffer(nitems).zipWith(RxView.clicks(v).debounce(500, TimeUnit.MILLISECONDS), (n, i) -> n))
.flatMap(new Function<List<String>, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(@NonNull final List<String> ids) throws Exception {
return Observable.from(ids)
}
}
)
.flatMap(new Function<String, ObservableSource<Item>>() {
@Override
public ObservableSource<Item> apply(@NonNull final String id) throws Exception {
return dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
}
}
});
}
编辑:您仍然需要使用 subscribeOn 来确保您在 RXView.clicks 的主线程上和任何网络的 IO 线程上。
不太好,但它有效:
你的获取方法:
Observable<Item> get(final String id){
return Observable.defer(() -> {
dataApi.get(id).map(new Function<Data, Item>() {
@Override
public Item apply(@NonNull Data data) throws Exception {
return new Item(data , id);
});
})
}
您的点击次数:
private List<String> ids = {//your id s}
private int current = 0;
RxView.clicks(view).flatmap(ignore -> get(ids.get(current++)))
.subscribe(//your Observer)
我想用 zipwith()
推荐那个答案,看起来比我的答案好。