android-fragments 添加从异步改造调用获得的项目后,Android RecyclerView仅包含一个项目

yshpjwxd  于 2022-11-14  发布在  Android
关注(0)|答案(3)|浏览(189)

我有一个简单的适配器图像显示回收视图。

  1. public class ImageListAdapter extends RecyclerView.Adapter<ImageListAdapter.SingleItemRowHolder> {
  2. private ArrayList<Bitmap> itemsList;
  3. public ImageListAdapter(ArrayList<Bitmap> itemsList) {
  4. this.itemsList = itemsList;
  5. }
  6. @Override
  7. public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
  8. View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.image_card, null);
  9. return new SingleItemRowHolder(v);
  10. }
  11. @Override
  12. public void onBindViewHolder(SingleItemRowHolder holder, int i) {
  13. Bitmap img = itemsList.get(i);
  14. holder.itemImage.setImageBitmap(img);
  15. }
  16. @Override
  17. public int getItemCount() {
  18. return (null != itemsList ? itemsList.size() : 0);
  19. }
  20. public void addItem(Bitmap image) {
  21. itemsList.add(image);
  22. notifyItemInserted(itemsList.size()-1);
  23. }
  24. public void setItemsList(ArrayList<Bitmap> bmps) {
  25. itemsList = bmps;
  26. }
  27. public ArrayList<Bitmap> getItemsList() {
  28. return itemsList;
  29. }
  30. public void cleanData() {
  31. itemsList = new ArrayList<>();
  32. notifyDataSetChanged();
  33. }
  34. public class SingleItemRowHolder extends RecyclerView.ViewHolder {
  35. protected ImageView itemImage;
  36. public SingleItemRowHolder(View view) {
  37. super(view);
  38. this.itemImage = (ImageView) view.findViewById(R.id.itemImage);
  39. }
  40. }
  41. }

这里没有什么复杂的。只是一个简单的适配器,获取位图列表作为输入,并显示在循环视图。
要点是,位图是通过一个改型调用异步添加的,如下所示:

  1. googleMapService.getImageByPhotoReference(s, 300, 300, apiKey).enqueue(new Callback<ResponseBody>() {
  2. @Override
  3. public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
  4. if (response.isSuccessful()) {
  5. if (response.body() != null) {
  6. Bitmap bmp = BitmapFactory.decodeStream(response.body().byteStream());
  7. adapter.addItem(bmp);
  8. }
  9. }
  10. }
  11. });

正如您在这里所看到的,位图被添加到适配器中,适配器应该能够通知这些更改,因为addItem()包含一个notifyItemInserted()调用。(有一个观察者在观察视图模型值的变化,一旦值发生变化,就会调用上面的reflection),所以改变视图模型值的代码看起来像这样:

  1. if (placeDetail.getPhotoRef() != null) {
  2. for (PlaceDetail.PhotoRef ref : placeDetail.getPhotoRef()) {
  3. viewModel.setPhoto(ref.getPhotoRef()); // ref.getPhotoRef returns the photo ref string
  4. }
  5. }

在我的预期中,适配器的项目列表现在应该包含几个图像。我试着调试它,我发现当调用addItem()方法时,项目列表的数量确实如预期的那样发生了变化。但是当它进入onBindViewHolder()回调时,项目列表中只剩下一个项目,即第一个位图。
有人能告诉我为什么会发生这个问题吗?任何建议都将不胜感激。
----------------------------------------------------------------------------------------------------更新-----------------------
有趣。我终于找到了为什么它只显示一张照片。正如你在这里看到的,适配器(X1 M4 N1 X)项目列表大小为4,这在我的预期中。

但是,存在另一个适配器(id:24962)。对于该适配器,add item方法只调用了一次,因此该适配器中只有一个项目。当回收器视图更改内容时,onBindViewHolder在第二个适配器上被调用。现在我的问题是,第二个适配器从哪里来???

下面是初始化回收器视图和适配器的代码

  1. @Override
  2. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
  3. @Nullable Bundle savedInstanceState) {
  4. binding = PlaceFragmentBinding.inflate(getLayoutInflater());
  5. RecyclerView recyclerView = binding.imageGallery;
  6. recyclerView.setHasFixedSize(true);
  7. ImageListAdapter adapter = new ImageListAdapter(new ArrayList<>());
  8. recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
  9. recyclerView.setAdapter(adapter);
  10. return binding.getRoot();
  11. }
6qftjkof

6qftjkof1#

你好,

  • 是否检查了是否是时间问题,因为您正在异步加载数据,这可能会导致缺少更新。
  • 也可能是setItemsList(ArrayList<Bitmap> bmps)被调用并覆盖当前列表?
  • 为什么不使用viewGroup作为扩展onCreateViewHolder()中的布局资源的基础?
  1. LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.image_card, viewGroup, false)
  • 在我看来,Adapter不应该是当前状态的保持器,也许有一个列表,并使用ListAdapter来显示它。当你有一个新的位图列表时,你只需调用adapter.submit(bitmaps),新的列表就会显示出来。与DiffCallback一起,旧的项目不会更新,新的项目会添加到列表的末尾。
kyxcudwk

kyxcudwk2#

让我们实现DiffUtils适配器,并尝试以这种方式更改您的调用。由于Kotlin可以与java互操作,因此我提到了用kotlin编写的适配器的要点。
Check adapter and view holder implementation
编码

  1. ImageListAdapter adapter;
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. binding = PlaceFragmentBinding.inflate(getLayoutInflater());
  6. View view = binding.getRoot();
  7. setContentView(view);
  8. }
  9. @Override
  10. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  11. binding.imageGallery.setHasFixedSize(true);
  12. adapter = new ImageListAdapter(new ArrayList<>());
  13. binding.imageGallery.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
  14. binding.imageGallery.setAdapter(adapter);
  15. return binding.getRoot();
  16. }

接口googleMapService

  1. Single<ResponseBody> getImageByPhotoReference(_,_,_,_)

网络呼叫

  1. googleMapService.getImageByPhotoReference(s, 300, 300, apiKey)
  2. .subscribeOn(Schedulers.io())
  3. .observeOn(AndroidSchedulers.mainThread())
  4. .subscribeWith(new DisposableSingleObserver<ResponseBody>() {
  5. @Override
  6. public void onSuccess(ResponseBody response) {
  7. if (response != null) {
  8. Bitmap bmp = BitmapFactory.decodeStream(response.body().byteStream());
  9. adapter.addItem(bmp);
  10. }
  11. }
  12. @Override
  13. public void onError(Throwable e) {
  14. // Do with your error
  15. }
  16. });
展开查看全部
0g0grzrc

0g0grzrc3#

有趣的是,在onCreateView方法中初始化adapter,它具有本地可见性(只在onCreateView方法内部可见)。但是在googleMapService.getImageByPhotoReference()方法的回调中,你引用了adapter.addItem(bmp);。所以我猜测你在googleMapService.getImageByPhotoReference()方法的回调中引用了错误的adapter对象。回调可能引用ImageListAdapter的旧示例。
尝试将ImageListAdapter adapter初始化为Fragment类的一个属性,看看它是否有效。

相关问题