在更改" SortBy"上,我的程序将执行NetworkIO以检索热门电影并显示它们。
但是,似乎虽然我已完成subscribeOn(Schedulers.io())
,但MovieDB.getPopular()
中的MovieDB.getTopRated()
函数中的NetworkIO call
和map
已在主要内容中执行线程,我得到android.os.NetworkOnMainThreadException
。
我想知道如何使public Movie[] call(SortBy sortBy)
异步。
sortObservable.map(new Func1<SortBy, Movie[]>() {
@Override
public Movie[] call(SortBy sortBy) {
try {
switch (sortBy) {
case POPULAR:
return MovieDB.getPopular(); // NETWORK IO
case TOP_RATED:
return MovieDB.getTopRated(); // NETWORK IO
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return new Movie[0];
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Movie[]>() {
@Override
public void call(Movie[] movies) {
imageAdapter.loadData(movies);
}
});
答案 0 :(得分:1)
最后,我自己解决了这个问题:
sortObservable.flatMap(new Func1<SortBy, Observable<Movie[]>>() {
@Override
public Observable<Movie[]> call(SortBy sortBy) {
switch (sortBy) {
case POPULAR:
return Observable.fromCallable(() -> MovieDB.getPopular()).subscribeOn(Schedulers.io());
case TOP_RATED:
return Observable.fromCallable(() -> MovieDB.getTopRated()).subscribeOn(Schedulers.io());
default:
return Observable.fromCallable(() -> new Movie[0]).subscribeOn(Schedulers.io());
}
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Movie[]>() {
@Override
public void call(Movie[] movies) {
imageAdapter.loadData(movies);
}
});
答案 1 :(得分:0)
请检查以下内容是否适合您。它使用flatMap
代替map
。
sortObservable.flatMap(new Func1<SortBy, Observable<Movie[]>>() {
@Override
public Observable<Movie[]> call(SortBy sortBy) {
try {
switch (sortBy) {
case POPULAR:
return Observable.just(MovieDB.getPopular()); // NETWORK IO
case TOP_RATED:
return Observable.just(MovieDB.getTopRated()); // NETWORK IO
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return Observable.just(new Movie[0]);
}
}).subscribe(new Action1<Movie[]>() {
@Override
public void call(Movie[] movies) {
imageAdapter.loadData(movies);
}
});
从Github上的源代码中,您似乎正在使用OkHttp执行请求的同步模式。 OkHttp还支持异步请求,这可能是首选。以下是几种方法所需的变化。
run
方法应使用enqueue
代替execute
。
Observable<String> runAsync(String url){
return Observable.create(subscriber -> {
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
subscriber.onNext(response.body().string());
}
@Override
public void onFailure(Call call, IOException e) {
subscriber.onError(e);
}
});
});
}
getApi
可以返回Observable<Movie[]>
而不是Movie[]
public Observable<Movie[]> getApiAsync(String type){
return runAsync("http://api.themoviedb.org/3/movie/" + type
+ "?api_key=412e9780d02673b7599233b1636a0f0e").flatMap(response -> {
Gson gson = new Gson();
Map<String, Object> map = gson.fromJson(response,
new TypeToken<Map<String, Object>>() {
}.getType());
Movie[] movies = gson.fromJson(gson.toJson(map.get("results")),
Movie[].class);
return Observable.just(movies);
});
}