我对反应式编程很新,但尝试应用rxjava来收集调用和短信列表并合并为单个。这个想法是以顺序方式迭代光标,顺序项发射。 在此之后,所有项目都被收集到单个列表中。
但是在doOnComplete
并非所有数据都被收集(我有大约150个项目,而且只有~25个被添加)。
我认为问题是Flowable.concat
并不等待所有项目,但这只是一个建议。
public void readLatestActivity() {
Cursor callsCursor = getCallsCursor();
Cursor smsCursor = getSmsCursor();
if (callsCursor == null || smsCursor == null) {
return;
}
SortedSet<MActivity> activities = new TreeSet<>((left, right) -> left.getReceiveTime() < right.getReceiveTime() ? 1 : 0);
Flowable.concat(getCallsPublisher(callsCursor), getSmsPublisher(smsCursor))
.subscribeOn(Schedulers.io())
.doOnNext(new Consumer<MActivity>() {
@Override
public void accept(@NonNull MActivity mActivity) throws Exception {
if (mActivity != null){
activities.add(mActivity);
}
}
})
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete(new Action() {
@Override
public void run() throws Exception {
Timber.d("doOnComplete");
callsCursor.close();
smsCursor.close();
mBus.post(new EActivities(activities)); //<--- here I'm getting ~25 items
}
})
.subscribe();
}
private Publisher<MActivity> getCallsPublisher(Cursor callsCursor) {
return Flowable.fromIterable(RxCursorIterable.from(callsCursor))
.take(callsCursor.getCount() < LIMIT ? callsCursor.getCount() : LIMIT)
.subscribeOn(Schedulers.computation())
.parallel()
.runOn(Schedulers.computation())
.map((Function<Cursor, MActivity>) this::readCallFromCursor)
.sequential()
.observeOn(AndroidSchedulers.mainThread());
}
private Publisher<MActivity> getSmsPublisher(Cursor smsCursor) {
return Flowable.fromIterable(RxCursorIterable.from(smsCursor))
.take(smsCursor.getCount() < LIMIT ? smsCursor.getCount() : LIMIT)
.subscribeOn(Schedulers.computation())
.parallel()
.runOn(Schedulers.computation())
.map((Function<Cursor, MActivity>) this::readSmsFromCursor)
.sequential()
.observeOn(AndroidSchedulers.mainThread());
}
读取短信和通话工作正常的方法。我认为问题出在其他地方。
此外,我发现了一个使cursor
行为像Iterable
public class RxCursorIterable implements Iterable<Cursor> {
private Cursor mIterableCursor;
public RxCursorIterable(Cursor c) {
mIterableCursor = c;
}
public static RxCursorIterable from(Cursor c) {
return new RxCursorIterable(c);
}
@Override
public Iterator<Cursor> iterator() {
return RxCursorIterator.from(mIterableCursor);
}
private static class RxCursorIterator implements Iterator<Cursor> {
private final Cursor mCursor;
public RxCursorIterator(Cursor cursor) {
mCursor = cursor;
}
public static Iterator<Cursor> from(Cursor cursor) {
return new RxCursorIterator(cursor);
}
@Override
public boolean hasNext() {
return !mCursor.isClosed() && mCursor.moveToNext();
}
@Override
public Cursor next() {
return mCursor;
}
}
}
答案 0 :(得分:1)
我认为问题在于您在创建TreeSet
时使用的比较器。 -1
时,它不会返回left.getReceiveTime() > right.getReceiveTime()
,即某些活动被错误地视为重复。
我还建议您简化getCallsPublisher
代码:
return Flowable.generate(getCallsCursor(),
(cursor, emitter) -> {
if (!cursor.isClosed() && cursor.moveToNext())
emitter.onNext(readCallFromCursor(cursor));
else
emitter.onComplete();
}, Cursor::close)
.take(LIMIT);
摆脱RxCursorIterable
。