如何解决使用DiffUtil,如何在更新NestedScrollView中包含的recyclerView时防止阻塞主线程?
我正在尝试在后台线程中对我的recyclerView进行审核,而没有任何成功。
更新recyclerView仍会阻塞主线程。
这是我的适配器:
public class PostAdapter extends RecyclerView.Adapter<PostAdapter.PostViewHolder> {
private List<PostItems> postList;
private Context context;
private Queue<List<PostItems>> pendingUpdates = new ArrayDeque<>();
PostAdapter(List<PostItems> postList,Context context) {
this.postList = postList;
this.context = context;
}
@NonNull
@Override
public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_view_wall_post,parent,false);
return new PostViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull PostViewHolder holder,int position) {
PostItems post_items = postList.get(position);
...
...
.........
...
...
}
@Override
public int getItemCount() {
return postList.size();
}
@Override
public int getItemViewType(int position) {
return position;
}
static class PostViewHolder extends RecyclerView.ViewHolder {
PostViewHolder(@NonNull View itemView) {
super(itemView);
...
...
.........
...
...
}
}
}
/*
* here the background Thread
*
*/
// The Fragment or Activity will call this method
// when new data becomes available
public void updateItems(final List<PostItems> newItems) {
pendingUpdates.add(newItems);
if (pendingUpdates.size() > 1) {
return;
}
updateItemsInternal(newItems);
}
// This method does the heavy lifting of
// pushing the work to the background thread
void updateItemsInternal(final List<PostItems> newItems) {
final List<PostItems> oldItems = new ArrayList<>(this.postList);
final Handler handler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
final DiffUtil.DiffResult diffResult =
DiffUtil.calculateDiff(new DiffCb(oldItems,newItems));
handler.post(new Runnable() {
@Override
public void run() {
applyDiffResult(newItems,diffResult);
}
});
}
}).start();
}
// This method is called when the background work is done
protected void applyDiffResult(List<PostItems> newItems,DiffUtil.DiffResult diffResult) {
pendingUpdates.remove();
dispatchUpdates(newItems,diffResult);
if (pendingUpdates.size() > 0) {
updateItemsInternal(pendingUpdates.peek());
}
}
// This method does the work of actually updating
// the backing data and notifying the adapter
protected void dispatchUpdates(List<PostItems> newItems,DiffUtil.DiffResult diffResult) {
diffResult.dispatchUpdatesTo(this);
postList.clear();
postList.addAll(newItems);
Toast.makeText(context,"b"+postList.size(),Toast.LENGTH_SHORT).show();
}
这是我的DiffUtil类:
class DiffCb extends DiffUtil.Callback {
private final List<PostItems> oldItems;
private final List<PostItems> newItems;
public DiffCb(List<PostItems> oldItems,List<PostItems> newItems) {
this.oldItems = oldItems;
this.newItems = newItems;
}
@Override
public int getOldListSize() {
return oldItems.size();
}
@Override
public int getNewListSize() {
return newItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition,int newItemPosition) {
return oldItems.get(oldItemPosition).equals(newItems.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition,int newItemPosition) {
return oldItems.get(oldItemPosition).equals(newItems.get(newItemPosition));
}
}
像这样更新recyclerView:
postList.addAll(response.body());
postAdapter.updateItems(homePostList);
当NestedScrollView或ScrollView中未包含我的recyclerView时,一切正常。
但是,当我的recyclerView包含在NestedScrollView或ScrollView中时,更新recyclerView会继续阻止main thread
,就像DiffUtil被禁用一样。
在更新NestedScrollView或ScrollView中包含的recyclerView时如何防止阻塞main thread
?
谢谢。
解决方法
尝试不要每次都创建新的适配器,而是在适配器内部更新数据。另外,如果您使用DiffUtils
,则应在.equals
类中覆盖.hashcode
和PostItems
,以便DIffUtils
知道哪个对象是新的,哪个对象已经存在。
在您的PostItems
班级某处单击鼠标右键,然后选择Generate
,然后选择override equals and hashcode
,然后在班级中选择唯一字段。
此外,您还应该在ViewHolder类中绑定视图
例如:
static class PostViewHolder extends RecyclerView.ViewHolder {
TextView tv1;
TextView tv2;
PostViewHolder(@NonNull View itemView) {
super(itemView);
tv1 = itemView.findViewById(R.id.tv1);
tv2 = itemView.findViewById(R.id.tv2);
}
}
然后通过.bindViewHolder
方法访问视图,如下所示:
@Override
public void onBindViewHolder(@NonNull PostViewHolder holder,int position) {
PostItems post_items = postList.get(position);
holder.tv1.setText(post_items.get_text_wall_post());
//etc
}
主要思想是不要在.findViewById()
方法中每次调用.bindViewHolder
,因为RecyclerView
的调用很慢
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。