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

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

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

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()调用。(有一个观察者在观察视图模型值的变化,一旦值发生变化,就会调用上面的reflection),所以改变视图模型值的代码看起来像这样:

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

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

但是,存在另一个适配器(id:24962)。对于该适配器,add item方法只调用了一次,因此该适配器中只有一个项目。当回收器视图更改内容时,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();
    }
6qftjkof

6qftjkof1#

你好,

  • 是否检查了是否是时间问题,因为您正在异步加载数据,这可能会导致缺少更新。
  • 也可能是setItemsList(ArrayList<Bitmap> bmps)被调用并覆盖当前列表?
  • 为什么不使用viewGroup作为扩展onCreateViewHolder()中的布局资源的基础?
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
编码

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
          }
  });
0g0grzrc

0g0grzrc3#

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

相关问题