[英]Android RecyclerView Adapter: how to implement notifyItemChanged thread safety?
在我的 RecyclerView.Adapter 上,我從 onBindViewHolder() 向 threadpoolexecutor 提交一個線程,以獲取我的 RecyclerView 向用戶顯示的 pdf 文件的預覽。
在那個線程完成它的事情之后,它應該調用 notifyItemChanged()。
問題是,當主線程調用諸如 notifyDataSetChanged() 之類的東西並且另一個線程嘗試調用 notifyItemChanged() 時,RecyclerView 會中斷(它會顯示先前的數據集,直到您滾動任意高度,以及更多奇怪的東西)。
我應該用什么來解決這些問題?
這是我的適配器(我刪除了所有不相關的代碼):
public class listAdapter extends RecyclerView.Adapter<listAdapter.ViewHolder> {
rejectionHandler rejectionHandler = new rejectionHandler();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
2000,
10, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(Runtime.getRuntime().availableProcessors()),
threadFactory, rejectionHandler
);
@SuppressLint("NotifyDataSetChanged")
public void updateAll(){
notifyDataSetChanged();
}
public listAdapter(Context context, FileViewerModel FVM, listType clType)
{Not relevant}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
//Removed non-relevant code
else if(!file.previewIsOnTheWay) switch (Utilities.getExtension(fileName)) {
case ".pdf":
file.previewIsOnTheWay = true;
executorPool.submit(new previewThread(file, this, FVM));
break;
//I removed other cases because it wasn't relevant.
}
}
@NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{}
}
這是我的預覽線程:
public class previewThread implements Runnable {
public previewThread(fileItem fileItem, listAdapter adapter, FileViewerModel fileViewerModel){
this.filePath= fileItem.getPath();
this.fileItem= fileItem;
this.adapter = adapter;
this.fvm = fileViewerModel;
}
@Override
public void run() {
switch (Utilities.getExtension(Objects.requireNonNull(filePath))) {
case ".pdf":
processPDF();
break;
default:
fileItem.previewResource = R.drawable.icon_preview; //TODO find document icon
}
if (Thread.interrupted()) return;
if (fvm.fileList.getValue().contains(fileItem)){
adapter.notifyItemChanged(fvm.fileList.getValue().indexOf(fileItem));
}
//I just need to call this line of code without breaking other stuff :(
}
private void processPDF() {Gives the fileItem a bitmap}
}
下面的鏈接詳細介紹了與 UI(mainThread)通信的后台線程。
https://developer.android.com/guide/background/threading#communicating-with-the-main-thread
代替
if (fvm.fileList.getValue().contains(fileItem)){
adapter.notifyItemChanged(fvm.fileList.getValue().indexOf(fileItem));
}
和
if (fvm.fileList.getValue().contains(fileItem)){
new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
adapter.notifyItemChanged(fvm.fileList.getValue().indexOf(fileItem));
}
}.sendEmptyMessage(1);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.