我有一个文件列表,我想从Android设备上传到后端。由于内存限制,我想在第一次完成之后进行第二次API调用,在第二次完成之后进行第三次API调用,依此类推。
我写了类似
的内容private Observable<Integer> uploadFiles(List<File> files) {
return Observable.create(subscriber -> {
for (int i = 0, size = files.size(); i < size; i++) {
UploadModel uploadModel = new UploadModel(files.get(0));
int uploadResult = retrofitApi.uploadSynchronously(uploadModel);
subscriber.onNext(uploadResult);
}
subscriber.onCompleted();
}).subscribeOn(Schedulers.newThread());
}
但是我觉得这可能违背了Rx的精神,而且说的是如果你使用的是Observable.create,你可能做错了...... 这是一种合理的方法吗?使用Retrofit的RxJava集成是否有更好的方法来实现这一目标?
答案 0 :(得分:4)
天真地,我会这样做(但是它不起作用,见下文):
function vote(event) {
event.preventDefault();
$.ajax({
url: "php/core/voting_system.php",
type: "POST",
dataType: 'html',
data: 'bad='+$('input[name="bad"]').val()+'&good='+$('input[name="good"]').val(),
success: function(data){
var votes = $("#votes").val().empty();
$("#votes").html(data+votes);
}
]);
}
现在的问题是,没有办法告诉改造仅使用一个线程进行这些调用。
但是, return Observable.from(files).concatMap(file -> retrofitApi.upload(uploadModel));
将一个函数调用的结果传递给下一个,以及原始observable的下一个发出值。这可行,但传递给reduce
的函数需要是同步的。不好。
另一种方法是递归修改observable:
reduce
大致。但我不知道如何清理它以使其更具可读性。
我认为最干净的是:
void getNextFile(int i) {
return retrofit.upload(i).
onNext(result -> getNextFile(i + 1));
}
答案 1 :(得分:0)
RxJava的原生代码会发出Observable.from(...)
中的所有项目,就像并行一样。这是将其视为平行排放的最佳方式。然而,有些情况需要真正的后续执行整个链。我已经得到了以下解决方案,可能不是最好的解决方案,而是工作。
import rx.Observable;
import rx.Subscriber;
import java.util.Iterator;
import java.util.function.Function;
public class Rx {
public static void ignore(Object arg) {
}
public static <E, R> Observable<Void> sequential(Iterator<E> iterator, Function<E, Observable<R>> action) {
return Observable.create(collectorSubscriber ->
Observable.<Void>create(producerSubscriber ->
producerSubscriber.setProducer(ignoredCount -> {
if (!iterator.hasNext()) {
producerSubscriber.onCompleted();
return;
}
E model = iterator.next();
action.apply(model)
.subscribe(
Rx::ignore,
producerSubscriber::onError,
() -> producerSubscriber.onNext(null));
}))
.subscribe(new Subscriber<Void>() {
@Override
public void onStart() {
request(1);
}
@Override
public void onCompleted() {
collectorSubscriber.onNext(null);
collectorSubscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
collectorSubscriber.onError(e);
}
@Override
public void onNext(Void aVoid) {
request(1);
}
}));
}
}
示例用法是:
Iterator<? extends Model> iterator = models.iterator();
Rx.sequential(iterator, model -> someFunctionReturnsObservable(model))
.subscribe(...);
此方法保证链接执行
Observable<Dummy> someFunctionReturnsObservable(Model model)
答案 2 :(得分:0)
目前,创建observable的首选方法是使用fromAsync:
Observable.fromAsync(new Action1<AsyncEmitter<Object>>()
{
@Override
public void call(final AsyncEmitter<Object> emitter)
{
emitter.onNext(object);
emitter.onCompleted();
emitter.setCancellation(new AsyncEmitter.Cancellable()
{
@Override
public void cancel() throws Exception
{
// on unSubscribe() callback
}
});
}
}, AsyncEmitter.BackpressureMode.BUFFER);