使用RxJava2
RxKotlin
和Room
,我需要查询数据库以进行开放式搜索。这意味着我搜索包含名为closed
且值为false
的属性的搜索。找到寻线后,需要将查询切换到特定的寻线。
我有两种查询方法:
getOpenHunt(teamId:String): Flowable<List<Hunt>>
getHunt(huntId:String): Flowable<List<Hunt>>
它们都返回List
,否则在没有找到寻线时查询会被卡住。
我的想法就像是
fun queryHunt(teamId:String):Flowable<Optional<Hunt>>{
getOpenHunt(teamId)
.map<Optional<Hunt>> {
Optional.create(it.firstOrNull())
}
.switchToFlowableIf ( it is Optional.Some, getHunt(it.element().id)
}
//With switchToFlowableIf's being
fun <E:Any> switchToFlowableIf(condition: (E)->Boolean, newFlowable: Flowable<E>): Flowable<E>
//It should unsubscribe from getOpenHunt and subscribe to newFlowable
供参考,这是我的Optional
课程
sealed class Optional<out T> {
class Some<out T>(val element: T) : Optional<T>()
object None : Optional<Nothing>()
fun element(): T? {
return when (this) {
is Optional.None -> null
is Optional.Some -> element
}
}
companion object {
fun <T> create(element: T?): Optional<T> {
return if (element != null) {
Optional.Some(element)
} else {
Optional.None
}
}
}
}
RxJava2中是否已经内置了类似的方法?如果没有,你会如何实现它?
答案 0 :(得分:1)
我通过查看onErrorResumeNext来解决这个问题。复制粘贴一些代码并修改为我的需要。我不认为这是完美的,但它确实是他的工作。如果您发现一些可能的错误,请发表评论。
public final class FlowableOnPredicateNext<T> extends AbstractFlowableWithUpstream<T, T> {
private final Predicate<? super T> predicate;
private final Function<? super T, ? extends Publisher<? extends T>> next;
public FlowableOnPredicateNext(Flowable<T> source, Predicate<? super T> predicate,
Function<? super T, ? extends Publisher<? extends T>> next) {
super(source);
this.predicate = predicate;
this.next = next;
}
@Override
protected void subscribeActual(Subscriber<? super T> s) {
OnPredicateNextSubscriber<T> parent = new OnPredicateNextSubscriber<>(s, next, predicate);
s.onSubscribe(parent.arbiter);
source.subscribe(parent);
}
static final class OnPredicateNextSubscriber<T> implements FlowableSubscriber<T> {
private final Subscriber<? super T> actual;
private final Predicate<? super T> predicate;
private final SubscriptionArbiter arbiter;
private final Function<? super T, ? extends Publisher<? extends T>> nextSupplier;
private boolean switched = false;
OnPredicateNextSubscriber(Subscriber<? super T> actual,
Function<? super T, ? extends Publisher<? extends T>>
nextSupplier, Predicate<? super T> predicate) {
this.actual = actual;
this.predicate = predicate;
this.nextSupplier = nextSupplier;
this.arbiter = new SubscriptionArbiter();
}
@Override
public void onSubscribe(Subscription s) {
arbiter.setSubscription(s);
}
@Override
public void onNext(T t) {
try {
if (!switched && predicate.test(t)) {
Publisher<? extends T> p;
p = nextSupplier.apply(t);
p.subscribe(this);
switched = true;
} else {
actual.onNext(t);
}
} catch (Exception e) {
actual.onError(e);
}
}
@Override
public void onError(Throwable t) {
actual.onError(t);
}
@Override
public void onComplete() {
actual.onComplete();
}
}
}
使用Kotlin我写了一个扩展函数:
@CheckReturnValue
@BackpressureSupport(BackpressureKind.FULL)
@SchedulerSupport(SchedulerSupport.NONE)
fun <E, T : Flowable<E>> T.onPredicateResumeNext(predicate: Predicate<E>, resumeFunction: io.reactivex.functions.Function<E, Publisher<E>>): Flowable<E> {
return RxJavaPlugins.onAssembly<E>(FlowableOnPredicateNext<E>(this,
predicate,
resumeFunction
))
}
我现在正在使用它:
override fun getOpenHunt(teamId: String): Flowable<Optional<Hunt>> {
return created().getOpenHunt(teamId)
.map {
Optional.create(it.firstOrNull())
}
.onPredicateResumeNext(predicate = Predicate { it.element() != null },
resumeFunction = Function {
created()
.getHunt(it.element()!!.id)
.map<Optional<Hunt>> {
Optional.create(it.firstOrNull())
}
})
}
答案 1 :(得分:0)
我会通过重复使用你的方法来做到这一点:
getOpenHunt(teamId:String): Flowable<List<Hunt>>
getHunt(huntId:String): Flowable<List<Hunt>>
getOpenHunt(yourId) // return your Flowable<List<Hunt>>
.flatMapIterable { it } // get each result of open hunts
.flatMapMaybe { getHunt(it.id) } // querie each result
.toList() // back to a Maybe/Single<List<Hunt>>
.toFlowable() // back to a Flowable else it wont emit more data
.subscribeBy(onNext = { /** process your results **/ },
onError = { /** process if no results found **/ }
)
这意味着如果有符合条件的条目,则查询数据库。然后它得到结果,将其拆分为单个项目,使用您的结果运行多个查询。如果找到结果,则会将其转换回Single<List<Hunt>>
。由于您希望继续订阅,因此需要使用.toFlowable()
顺便说一下,更改意味着返回值会更改,但在您的情况下,它会相同List<Hunt>
。
整个流程对我来说没有任何意义,因为你也可以通过getOpenHunt得到结果并迭代它。