RxJava 2:flatMapCompletable不等待Completable完成

时间:2018-08-12 11:34:47

标签: android rx-java retrofit2 rx-java2 rx-android

用例:有一个POJO类的数据集。在这种情况下,它是ArrayList。我创建了一个类,它扩展了ArrayList并提供了一些帮助程序方法,该方法将列表分为页面。页面仅将列表分成小页面,以上传到REST API。我从Iterable创建了一个Iterator,该工具检查页面是否可用于上传,然后获取该页面。该页面需要上传,并且一旦上传成功,它将被删除,然后再次需要下一页。此过程必须继续从列表中连续上传每个页面,直到页面为空。

代码:(此处模拟了API调用)

import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.schedulers.Schedulers;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Sample {

    public static void main(String[] args) {
        Store store = new Store();

        for (int i = 0; i < 20; i++)
            store.add("Sample value");

        store.getPageStream()
                .flatMapCompletable(in -> getApi().doOnComplete(store::removePage))
                .subscribe(() -> System.out.println("Job done"), Throwable::printStackTrace);

    }

    private static Completable getApi() {
        return Completable.create(emitter -> {

            System.out.println("API Requesting");
            Thread.sleep(2000);
            System.out.println("API Done\n\n");
            emitter.onComplete();

        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

}

class Store extends ArrayList<String> {

    private static final int PAGE_SIZE = 3;

    private final Object pageLock = new Object();
    private final Iterator<List<String>> iterator = new Iterator<List<String>>() {

        @Override
        public boolean hasNext() {
            return isAvailable();
        }

        @Override
        public List<String> next() {
            return getPage();
        }

    };

    private int lastPageSize = 0;

    Flowable<List<String>> getPageStream() {
        return Flowable.fromIterable(() -> iterator);
    }

    private List<String> getPage() {
        synchronized (pageLock) {
            List<String> temp = new ArrayList<>();

            lastPageSize = Math.min(size(), PAGE_SIZE);

            for (int i = 0; i < lastPageSize; i++)
                temp.add(get(i));
            return temp;
        }
    }

    void removePage() {
        synchronized (pageLock) {
            if (lastPageSize <= 0)
                return;

            System.out.println(toString());
            removeRange(0, lastPageSize);
            lastPageSize = 0;
            System.out.println(toString());
        }
    }

    private boolean isAvailable() {
        synchronized (pageLock) {
            return size() > 0;
        }
    }

}

问题是:该过程不是连续发生的。 flatMapCompletable在请求下一页之前没有等待API完成。而且,由于它不断地请求页面而不删除它们,所以它永远不会完成。

其他信息::如果我从.subscribeOn(Schedulers.io())方法中删除了行getApi(),则调用会依次发生,并且效果很好,但会导致NetworkOnMainThreadException

在此先感谢您能解决这个问题。

0 个答案:

没有答案