我当前的Android应用程序使用LiveData填充我的recyclerView。
有些用户有1000个项目要显示。
我还允许我的用户搜索/过滤回收器视图中的项目。
列表的初始显示很好。
然而,当用户开始搜索/过滤从1000到1或2个项目的列表时,用户体验确实变得非常差,UI在10秒内变得没有响应。
我的RecyclerView适配器使用android.support.v7.util.DiffUtil来管理列表项更改。
我尝试在我的活动onChange方法中使用RxJava在后台线程上执行diffing
Observable.just(newItems)
.doOnSubscribe(compositeDisposable::add)
.subscribeOn(Schedulers.io())
.switchMap(new Function<List<ItemUI>, ObservableSource<DiffUtil.DiffResult>>() {
@Override
public ObservableSource<DiffUtil.DiffResult> apply(final List<ItemUI> itemUIs) {
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(adapter.getCurrentItems(), newItems));
return Observable.just(diffResult);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<DiffUtil.DiffResult>() {
@Override
public void accept(final DiffUtil.DiffResult diffResult) {
adapter.updateList(diffResult, articles);
}
});
My Adapter up[dateList方法类似于此
public void updateList(final DiffUtil.DiffResult diffResult, final List<ItemUI> newItems) {
this.items.clear();
this.items.addAll(newItems);
diffResult.dispatchUpdatesTo(this);
}
我仍然看到像这个这样的logcat消息
Choreographer: Skipped 200 frames! The application may be doing too much work on its main thread.
我犯了什么错误,仍然看到跳过的帧?
是否可以区分大列表的更改,并且仍然具有响应UI?
尝试以下操作:
Observable.just(newItems)
.observeOn(Schedulers.io()) // <------------------------------------
.map(new Function<List<ItemUI>, DiffUtil.DiffResult>() {
@Override
public DiffUtil.DiffResult apply(final List<ItemUI> itemUIs) {
return DiffUtil.calculateDiff(
new GenericDiffUtilCallback<>(
adapter.getCurrentItems(), itemUIs));
}
})
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(compositeDisposable::add) // <------------------------
.subscribe(new Consumer<DiffUtil.DiffResult>() {
@Override
public void accept(final DiffUtil.DiffResult diffResult) {
adapter.updateList(diffResult, articles);
}
});
你其实并不需要switchMap
。此外,如果你真的想让dispose生效,你必须尽可能地将其向下移动,否则原始问题中的位置将不会对其下面的diff计算产生影响。
我还想检查一下你是否无意中遇到了线程问题,比如这个博客中描述的情况
编辑:
如果您有更改源,您可以使用switchMap
,但也可以使用fromCallable
:
.switchMap(itemUIs -> {
return Observable.fromCallable(() ->
DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(
adapter.getCurrentItems(), itemUIs))
)
.subscribeOn(Schedulers.computation());
})