我有一個帶有簡單配接器的影像顯示回收器視圖。
public class ImageListAdapter extends RecyclerView.Adapter<ImageListAdapter.SingleItemRowHolder> {
private ArrayList<Bitmap> itemsList;
public ImageListAdapter(ArrayList<Bitmap> itemsList) {
this.itemsList = itemsList;
}
@Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.image_card, null);
return new SingleItemRowHolder(v);
}
@Override
public void onBindViewHolder(SingleItemRowHolder holder, int i) {
Bitmap img = itemsList.get(i);
holder.itemImage.setImageBitmap(img);
}
@Override
public int getItemCount() {
return (null != itemsList ? itemsList.size() : 0);
}
public void addItem(Bitmap image) {
itemsList.add(image);
notifyItemInserted(itemsList.size()-1);
}
public void setItemsList(ArrayList<Bitmap> bmps) {
itemsList = bmps;
}
public ArrayList<Bitmap> getItemsList() {
return itemsList;
}
public void cleanData() {
itemsList = new ArrayList<>();
notifyDataSetChanged();
}
public class SingleItemRowHolder extends RecyclerView.ViewHolder {
protected ImageView itemImage;
public SingleItemRowHolder(View view) {
super(view);
this.itemImage = (ImageView) view.findViewById(R.id.itemImage);
}
}
}
這里沒有什么復雜的。只是一個簡單的配接器,它獲取位圖串列作為輸入并在回收視圖中顯示它們。
關鍵是,位圖是通過改造呼叫異步添加的,如下所示:
googleMapService.getImageByPhotoReference(s, 300, 300, apiKey).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
Bitmap bmp = BitmapFactory.decodeStream(response.body().byteStream());
adapter.addItem(bmp);
}
}
}
});
正如您在此處看到的,位圖已添加到配接器,并且配接器應該能夠通知更改addItem()包含notifyItemInserted()呼叫。并且這個retrofit呼叫會被呼叫幾次,具體取決于視圖模型改變了它的值的次數(有一個觀察者觀察視圖模型的值的變化。一旦值改變,上面的retrofit就會被呼叫)。因此更改視圖模型值的代碼如下所示:
if (placeDetail.getPhotoRef() != null) {
for (PlaceDetail.PhotoRef ref : placeDetail.getPhotoRef()) {
viewModel.setPhoto(ref.getPhotoRef()); // ref.getPhotoRef returns the photo ref string
}
}
在我的預期中,配接器的專案串列現在應該包含幾個影像。我試圖除錯它,我發現當addItem()方法被呼叫時,專案串列的數量確實按預期發生了變化。但是當它進入onBindViewHolder()回呼時,專案串列中只剩下一個專案,即第一個位圖。
誰能告訴我為什么會出現這個問題?任何建議將不勝感激。
----------------------------------更新---------------- -----------------
有趣的。我終于找到了為什么它只顯示一張照片。正如您在此處看到的,配接器 ( id:24856) 專案串列大小為 4,這是我的預期。

但是,還有另一個配接器(id:24962)存在。對于該配接器,添加項方法僅呼叫一次,因此該配接器中只有一項。當回收器視圖更改內容時,onBindViewHolder會在第二個配接器上呼叫 。現在我的問題是,第二個配接器來自哪里???

這是我初始化回收站視圖和配接器的代碼
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = PlaceFragmentBinding.inflate(getLayoutInflater());
RecyclerView recyclerView = binding.imageGallery;
recyclerView.setHasFixedSize(true);
ImageListAdapter adapter = new ImageListAdapter(new ArrayList<>());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
recyclerView.setAdapter(adapter);
return binding.getRoot();
}
uj5u.com熱心網友回復:
Hej AhSoHard,
您是否檢查了這是否是時間問題,因為您正在異步加載資料,并且可能導致更新丟失。
也可能是
setItemsList(ArrayList<Bitmap> bmps)被呼叫并覆寫當前串列嗎?您是否有理由不將
viewGroup用作擴展布局資源的基礎onCreateViewHolder()?
LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.image_card, viewGroup, false)
- 在我看來,
Adapter不應該是當前狀態的持有者,也許在外面有一個串列并使用ListAdapter來顯示它。當您有一個新的位圖串列時,您只需呼叫adapter.submit(bitmaps)并顯示新串列。與DiffCallback一起,舊專案不會更新,新專案將添加到串列末尾。
uj5u.com熱心網友回復:
讓我們實作 DiffUtils 配接器并嘗試以這種方式更改您的呼叫。由于 kotlin 可以與 java 互操作,因此我提到了用 kotlin 撰寫的配接器的要點。
檢查配接器和視圖支架實作
代碼
ImageListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = PlaceFragmentBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding.imageGallery.setHasFixedSize(true);
adapter = new ImageListAdapter(new ArrayList<>());
binding.imageGallery.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
binding.imageGallery.setAdapter(adapter);
return binding.getRoot();
}
介面 googleMapService
Single<ResponseBody> getImageByPhotoReference(_,_,_,_)
網路通話
googleMapService.getImageByPhotoReference(s, 300, 300, apiKey)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<ResponseBody>() {
@Override
public void onSuccess(ResponseBody response) {
if (response != null) {
Bitmap bmp = BitmapFactory.decodeStream(response.body().byteStream());
adapter.addItem(bmp);
}
}
@Override
public void onError(Throwable e) {
// Do with your error
}
});
uj5u.com熱心網友回復:
有趣的是,您初始化了adapterinonCreateView方法并且它具有本地可見性(僅在onCreateView方法內部可見)。但是在googleMapService.getImageByPhotoReference()方法的回呼中,您正在參考它adapter.addItem(bmp);。所以我的猜測是你在方法的回呼中參考了錯誤的adapter物件。googleMapService.getImageByPhotoReference()回呼可能會參考ImageListAdapter.
嘗試初始化ImageListAdapter adapter為你的Fragment類的屬性,看看它是否有效。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/477790.html
標籤:安卓 异步 安卓片段 android-recyclerview 改造
