RecyclerView 在更新期间阻塞 ui 线程

sor*_*dam 2 android ui-thread android-runonuithread android-recyclerview

我的清单中有 200 多个项目。RecyclerView 定期更新(每 10 秒)。RecyclerView 在更新期间阻塞 ui 线程几秒钟。我正在使用 notifyDataSetChanged刷新 recyclerview 的方法。有没有其他方法可以防止冻结?顺便说一句,我不想​​使用分页。

此方法每 10 秒运行一次:

public void refreshAssetList(List<Asset> newAssetList){
     recyclerViewAdapter.setAssetList(newAssetList);
     recyclerViewAdapter.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)

RecyclerViewAdapter 类:

public class AssetListRecyclerViewAdapter extends RecyclerView.Adapter<AssetListRecyclerViewAdapter.BaseViewHolder> {

    private List<Asset> assetList;
    Context context;

    public AssetListRecyclerViewAdapter(List<Asset> assetList, Context context) {
        this.assetList = assetList;
        this.context = context;
    }

    public void setAssetList(List<Asset> assetList) {
        this.assetList = assetList;
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_asset, null);
            return new DetailViewHolder(itemLayoutView);
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        Asset asset = assetList.get(position);
        Last last = asset.getLast();
        if (holder.getItemViewType() == TYPE_DETAIL) {
            DetailViewHolder mHolder = (DetailViewHolder) holder;
            mHolder.dateTextView.setText(last.getDate());
            mHolder.brandTextView.setText(asset.getMc());
        }
    }

     class DetailViewHolder extends BaseViewHolder {

        @Bind(R.id.brandTextV)
        TextView brandTextView;
        @Bind(R.id.dateTextV)
        TextView dateTextView;

         DetailViewHolder(View itemLayoutView) {
            super(itemLayoutView);
            ButterKnife.bind(this, itemLayoutView);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

Har*_*shi 5

您不需要调用notifyDataSetChanged,这是一项昂贵的操作,您的整体RecyclerView将完全重绘、重新绑定等。

正如文档所说:

此事件未指定数据集发生了什么变化,迫使任何观察者假设所有现有项目和结构可能不再有效。LayoutManagers 将被迫完全重新绑定和重新布局所有可见视图。

您需要做的就是遍历每个位置,如果需要更新所需的项目,否则什么都不做或跳过。

你应该做什么:

当您首先更新您的整个视图时,您需要将您的(可见)适配器List<Asset>与 new进行比较,List<Asset>并仅检索您需要更新的那些项目,一旦您的列表循环通过更新的列表并使用viewAdapter.notifyItemChanged(position).