I have a recycler view for image display with a simple adapter.
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);
}
}
}
Nothing complex here. Just a simple adapter that getting bitmap list as input and show them in the recycle view.
The point is, the bitmaps are asynchronously added via a retrofit call, as shown in the folloing:
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);
}
}
}
});
As you can see here, the bitmap is added to the adapter and the adapter should be able to notify the changes as addItem() contains a notifyItemInserted() call. And this retrofit call is called several times depending on how many times the view model has changes its value (there is a observer observing the change of view model's value. Once the value changes, the above retrofit will get called). So the code that changes view model value look like this:
if (placeDetail.getPhotoRef() != null) {
for (PlaceDetail.PhotoRef ref : placeDetail.getPhotoRef()) {
viewModel.setPhoto(ref.getPhotoRef()); // ref.getPhotoRef returns the photo ref string
}
}
In my expectation, the item list of the adapter should now contains several images. I tried to debug it, and I found when the addItem() method get called, the amount of item list did change as expected. But when it came into the onBindViewHolder() callback, there is only one item left in the item list, which is the first bitmap.
Can anyone tell me why this issue happened? Any suggestion would be appreciated.
---------------------------------- Update --------------------------------
Interesting. I finally found why it only shows one photo. As you can see here, the adapter (id:24856) item list size is 4, which is in my expectation.
However, there is another adapter(id:24962) exists. For that adapter, the add item method only called once thus only one item in that adapter. When the recycler view changes the content, the onBindViewHolder is called on the second adapter. Now my question is, where does the second adapter come from ???
Here is my code to initialize recycler view and adapter
@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();
}
from Android RecyclerView only contain one item after adding items got from asynchronous retrofit calls


No comments:
Post a Comment