我将尝试创建一个管理器,监测 Obsevable<List>
中所有服务是否已经准备就绪。
这段代码的总体思路类似于下面的代码:
public class ServiceStuff {
public interface Service {
String getName();
Observable<Boolean> monitorReady();
}
private BehaviorSubject<List<Service>> services = BehaviorSubject.createDefault(Collections.emptyList());
ServiceStuff(List<Service> list) {
services.onNext(list);
}
public void addService(Service service) {
List<Service> newList = services.getValue();
newList.add(service);
services.onNext(newList);
}
public void removeService(Service service) {
List<Service> newList = services.getValue();
newList.remove(service);
if (newList.remove(service)) {
services.onNext(newList);
}
}
public Observable<List<Service>> monitorServices() {
return services.observeOn(AndroidSchedulers.mainThread());
}
public Observable<Boolean> monitorServicesReady() {
return [If monitorReady() for all services return true, emit true, else false]
}
}
如何在不阻塞UI线程的情况下实现monitorServicesReady()
方法?应该可以在添加任何服务之前开始监视。
更新:
我现在尝试了cyroxis建议的解决方案,并进行了一些修改。 blockingIterable()
会导致应用程序ANR,因为它永远不知道monitorServices()
流何时结束。
public Observable<Boolean> monitorServicesReady() {
Iterable<Observable<Boolean>> sources = monitorServices().flatMapIterable(x -> x).map(Service::monitorReady).blockingIterable();
return Observable.combineLatest(sources, this::all);
}
private boolean all(Object[] values) {
boolean result = true;
for (boolean val : (Boolean[]) values) {
result &= val;
}
return result;
}
monitorServicesReady()
不应该阻塞UI线程吗? - Saeed MasoumiblockingGet()
来解决这个问题 :) - MisseMaskList<Observable<Boolean>>
,而你的 combiner(例如all
)需要 Object[] 类型,不能使用 Boolean[],所以你必须在方法内部进行类型转换。 - cyroxiscombineLatest(sources, this::all)
中的第一个参数必须是Iterable<Observable<Boolean>>
。但是我不想使用blockingIterable()
,因为那会阻塞 UI 线程,对吧?或者调用monitorServicesReady()
的人会注意到这一点吗? - MisseMask