我想在android中使用RXJava对后台线程进行长时间的计算。经过计算,我试图在Recylerview中显示结果。我正在使用以下代码:
Observable.just("true")
.subscribeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String s) {
feedlist.clear();
if (eventFeedItems != null && !eventFeedItems.isEmpty()) {
for (int i = 0; i < eventFeedItems.size(); i++) {
if (eventFeedItems != null && eventFeedItems.get(i) != null
&& ((eventFeedItems.get(i).getType() != null && eventFeedItems.get(i).getType().equalsIgnoreCase("EVENT"))
|| (eventFeedItems.get(i).getActivityRequestType() != null && eventFeedItems.get(i).getActivityRequestType().equalsIgnoreCase(EventConstants.TRENDING_ACTIVITY)))) {
if (eventFeedItems.get(i).getActivityRequestType() != null && !eventFeedItems.get(i).getActivityRequestType().equalsIgnoreCase("")) {
feedlist.add(new FeedsListModel(eventFeedItems.get(i), eventFeedItems.get(i).getActivityRequestType(), null));
} else if (eventFeedItems.get(i).getRequestType() != null && !eventFeedItems.get(i).getRequestType().equalsIgnoreCase("")) {
feedlist.add(new FeedsListModel(eventFeedItems.get(i), eventFeedItems.get(i).getRequestType(), null));
} else
feedlist.add(new FeedsListModel(eventFeedItems.get(i), EventConstants.ATTENDEE_POST, null));
}
}
}
Log.d("calculations","Completed");
return "";
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
// feed_list.setLayoutManager(mLayoutManager);
// feedListAdapter.notifyDataSetChanged();
Log.d("Adapter", "Set");
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.d("Exception", "oh! fish...");
throwable.printStackTrace();
}
});
&#13;
使用上面这段代码,我面对UI Hindring,因为ArrayList eventFeedItems大小大约有300多个项目。我是RXJava的新手。请帮帮我。
答案 0 :(得分:4)
你不会使用map-Operator实现并发。
第一个subscribeOn会将所有emitions移动到IO-scheduler。这里没有发生并发。
.subscribeOn(Schedulers.io())
将从前一个线程同步调用map-operator。在你的情况下,它将来自IO-threadpool。
.map(new Func1<String, String>() {
执行map-Operator后,您将使用
将值从IO线程移动到Android-UI事件循环.observeOn(AndroidSchedulers.mainThread())
将值从IO线程转换为UI线程后,将处理初始observable中的下一个值。
Observable.just("true")
在您的示例中,将不再有值,因为您只生成一个值。
为了实现并发,您应该使用flatMap而不是map。并使用flatMap中的subscribeOn()在另一个线程上创建每个流。
请考虑此示例,以了解并发性如何发生。每个可观察者都会立即订阅,所以最大值。 teset的时间约为5秒。如果现在发生并发,则需要1 + 2 + 3 + 4 + 5秒加上执行时间。
@Test
public void name1() throws Exception {
Observable<Integer> value = Observable.just(1_000, 2_000, 3_000, 4_000, 5_000)
.flatMap(i -> Observable.fromCallable(() -> doWork(i)).subscribeOn(Schedulers.io())
).doOnNext(integer -> System.out.println("value"));
value.test().awaitTerminalEvent();
}
private int doWork(int sleepMilli) {
try {
Thread.sleep(sleepMilli);
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
如果您想了解更多关于flatMap如何发生并发的信息,请考虑阅读http://tomstechnicalblog.blogspot.de/2015/11/rxjava-achieving-parallelization.html
关于你的代码,我建议:
不要将副作用用于来自其中的运算符的全局变量。您 如果涉及并发,将会遇到竞争条件。
List<FeedsListModel> eventFeedItems = Arrays.asList(new FeedsListModel(), new FeedsListModel());
Observable<FeedsListModel> feedsListModelObservable = Observable.fromIterable(eventFeedItems)
.flatMap(feedsListModel -> Observable.fromCallable(() -> calculation(feedsListModel))
.subscribeOn(Schedulers.computation())
);
feedsListModelObservable
.toList()
.observeOn(Schedulers.io())
.subscribe(feedsListModels -> {
// do UI stuff
});
帮助-方法:
private FeedsListModel calculation(FeedsListModel model) {
// do calculation here
return new FeedsListModel();
}