我在使用zip运算符组合多个observable时面临android.os.NetworkOnMainThreadException。据我所知,我正在使用适当的调度程序。
public void loadFeeds(final String... urls) {
final List<Observable<Response>> observables = new ArrayList<>();
for (String url : urls) {
try {
observables.add(Observable.just(RssParser.parse(url)));
} catch (IOException e) {
e.printStackTrace();
}
}
Observable<List<RSS>> rssListObservable = Observable.zip(observables, new Function<Object[], List<RSS>>() {
public List<RSS> apply(Object[] objects) throws Exception {
final List<RSS> rssList = new ArrayList<RSS>();
for (Object object : objects) {
Response response = (Response) object;
RSS rss = new Persister().read(RSS.class, response.body().string());
rssList.add(rss);
}
return rssList;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
disposable = rssListObservable.subscribeWith(new DisposableObserver<List<RSS>>() {
@Override
public void onNext(List<RSS> rssList) {
//rssCallback.rssFeedsLoaded(rssList);
Log.d(TAG, "onNext: rssListSize: "+rssList.size());
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage(), e);
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: done");
}
});
}
我正在使用Observable.just()
将此方法转换为observablestatic Response parse(String feedUrl) throws IOException {
Request request = new Request.Builder()
.url(feedUrl)
.get()
.build();
return OK_HTTP_CLIENT.newCall(request).execute();
}
以下是错误日志:
FATAL EXCEPTION: main
Process: com.crazyhitty.chdev.ks.rssmanagerlib, PID: 18980
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
at java.net.InetAddress.getAllByName(InetAddress.java:752)
at okhttp3.Dns$1.lookup(Dns.java:39)
at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:170)
at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.java:136)
at okhttp3.internal.connection.RouteSelector.next(RouteSelector.java:81)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:171)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
at okhttp3.RealCall.execute(RealCall.java:63)
at com.crazyhitty.chdev.ks.rssmanager.RssParser.parse(RssParser.java:29)
at com.crazyhitty.chdev.ks.rssmanager.RssReader.loadFeeds(RssReader.java:43)
at com.crazyhitty.chdev.ks.rssmanagerlib.MainActivity.loadFeeds(MainActivity.java:72)
at com.crazyhitty.chdev.ks.rssmanagerlib.MainActivity.access$200(MainActivity.java:21)
at com.crazyhitty.chdev.ks.rssmanagerlib.MainActivity$1.onClick(MainActivity.java:54)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
感谢任何形式的帮助或指导,谢谢:)
编辑:找到解决方案的人,基本上作为一个RxJava新手,我不知道Observable.just()立即执行当前线程上的observable。因此,不应使用Observable.just(),而应在此类场景中使用Observable.create()。
固定代码:
public void loadFeeds(final String... urls) {
final long startTimeMillis=System.currentTimeMillis();
final List<Observable<RSS>> observables = new ArrayList<>();
for (final String url : urls) {
observables.add(Observable.create(new ObservableOnSubscribe<RSS>() {
@Override
public void subscribe(ObservableEmitter<RSS> emitter) throws Exception {
RSS rss = new Persister().read(RSS.class, RssParser.parse(url).body().string());
Log.d(TAG, "subscribe: url: " + url + " ; thread: " + Thread.currentThread().getName());
emitter.onNext(rss);
emitter.onComplete();
}
}));
}
Observable<List<RSS>> rssListObservable = Observable.zip(observables, new Function<Object[], List<RSS>>() {
@Override
public List<RSS> apply(Object[] objects) throws Exception {
final List<RSS> rssList = new ArrayList<RSS>();
for (Object object : objects) {
rssList.add((RSS) object);
}
return rssList;
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
disposable = rssListObservable.subscribeWith(new DisposableObserver<List<RSS>>() {
@Override
public void onNext(List<RSS> rssList) {
rssCallback.rssFeedsLoaded(rssList);
Log.d(TAG, "onNext: rssListSize: " + rssList.size());
}
@Override
public void onError(Throwable e) {
rssCallback.unableToReadRssFeeds(e.getMessage());
Log.e(TAG, "onError: " + e.getMessage(), e);
}
@Override
public void onComplete() {
Log.d(TAG, String.format(Locale.ENGLISH, "onComplete: done with time spent(ms): %d", (System.currentTimeMillis()-startTimeMillis)));
}
});
}