根据官方文档站点https://github.com/ReactiveX/RxJava/wiki/Connectable-Observable-Operators上的小样本,ConnectableObservable应该同时运行与每个可观察对象关联的操作,但是我正在研究https://www.androidhive.info/RxJava/flatmap-concatmap-operators-flight-tickets-app/中的以下示例代码似乎与每个观察者相关的工作都是按顺序运行的,即使他使用的是ConnectableObservable。我认为这与Schedulers.io()有关,但此调度程序由无限制的线程池支持,因此,从理论上讲,它有多个可用的单个线程来处理两个工作负载,除非我遗漏了一些东西(我肯定是)。 Schedulers.io()是同步还是异步运行作业?或者换一种说法,为什么与两个观察员相关的工作都按顺序进行?为什么第二个观察者可以安全地假设与第一个观察者相关的工作是在它开始处理自己的工作负载之前完成的?
ConnectableObservable<List<Ticket>> ticketsObservable = getTickets(from, to).replay();
/**
* Fetching all tickets first
* Observable emits List<Ticket> at once
* All the items will be added to RecyclerView
* */
disposable.add(
ticketsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<List<Ticket>>() {
@Override
public void onNext(List<Ticket> tickets) {
// Refreshing list
ticketsList.clear();
ticketsList.addAll(tickets);
mAdapter.notifyDataSetChanged();
}
@Override
public void onError(Throwable e) {
showError(e);
}
@Override
public void onComplete() {
}
}));
/**
* Fetching individual ticket price
* First FlatMap converts single List<Ticket> to multiple emissions
* Second FlatMap makes HTTP call on each Ticket emission
* */
disposable.add(
ticketsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
/**
* Converting List<Ticket> emission to single Ticket emissions
* */
.flatMap(new Function<List<Ticket>, ObservableSource<Ticket>>() {
@Override
public ObservableSource<Ticket> apply(List<Ticket> tickets) throws Exception {
return Observable.fromIterable(tickets);
}
})
/**
* Fetching price on each Ticket emission
* */
.flatMap(new Function<Ticket, ObservableSource<Ticket>>() {
@Override
public ObservableSource<Ticket> apply(Ticket ticket) throws Exception {
return getPriceObservable(ticket);
}
})
.subscribeWith(new DisposableObserver<Ticket>() {
@Override
public void onNext(Ticket ticket) {
int position = ticketsList.indexOf(ticket);
if (position == -1) {
// TODO - take action
// Ticket not found in the list
// This shouldn't happen
return;
}
ticketsList.set(position, ticket);
mAdapter.notifyItemChanged(position);
}
@Override
public void onError(Throwable e) {
showError(e);
}
@Override
public void onComplete() {
}
}));
// Calling connect to start emission
ticketsObservable.connect();
答案 0 :(得分:1)
Scheduler
允许工作在执行上下文中运行; Scheduler.io(), the context is a pool of threads. The
observeOn()操作符的作用是告诉观察者链在该上下文中运行。
但是,实际上它的工作方式是只有一个线程在运行观察者链,因为这就是您要使用的全部。因为observerOn()
仅被调用一次,所以在实例化观察者链时,只有一个线程可用。如果您多次实例化观察者,则每次都会从池中选择一个线程并将该线程用于特定实例。
关于观察者链的运作有一些规则;其中,一次只能有一个线程可以将值发送到链中。通常,任何观察者链都完全由单个线程执行,因此默认情况下满足约束条件。
使用subscribeOn()
,observeOn()
和其他隐式或显式选择调度程序的运算符,您可以控制何时以及如何在线程之间划分工作。将这些运算符放在链中的位置很重要。
例如,如果将observeOn(Schedulers.io())
运算符放在第一个flatMap()
运算符之后 ,那么您将得到不同的结果。 flatMap()
为每个输入启动一个新的观察者链;每个观察者链可能都有自己的线程。