Android RecyclerView content not updating after notifyItemInserted - java

I've got a RecyclerView that needs to update in real-time when content is received. It successfully shows all the content at first load. When attempting to add a new item dynamically, it makes no difference. Is there anything I'm doing wrong here? Much appreciated!
MainActivity:
RecyclerView rvClips;
ClipboardRVAdapter adapter;
ArrayList<Clip> clips = new ArrayList<>();
private void SetupRV() {
adapter = new ClipboardRVAdapter(clips);
rvClips.setAdapter(adapter);
adapter.setClickListener(this);
rvClips.setLayoutManager(new LinearLayoutManager(getActivity()));
}
//this method gets called everytime a new item is received. I confirmed that it gets called.
public void OnNewClipReceived(Clip clip) {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
Adapter:
Standard adapter code. Simply shows all the items in the recyclerview.
public class ClipboardRVAdapter extends RecyclerView.Adapter<ClipboardRVAdapter.ViewHolder> {
private ItemClickListener mClickListener;
ArrayList<Clip> clips;
public ClipboardRVAdapter(ArrayList<Clip> clips) {
this.clips = clips;
}
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
public interface ItemClickListener {
void onItemClick(View view, int position);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_clipboard_clip, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Clip clip = clips.get(position);
holder.tvClipTitle.setText(clip.content);
}
#Override
public int getItemCount() {
return clips.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tvClipTitle;
public ViewHolder(View itemView) {
super(itemView);
tvClipTitle = itemView.findViewById(R.id.tvClipTitle);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
}

Since you mentioned 'realtime', I'm guessing this could be a thread issue. Your code seems correct. It could be that the adapter needs to be refreshed in a runOnUiThread function. Try this:
public void OnNewClipReceived(Clip clip) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
});
}

You would need this method in your RecyclerView adapter.
void addNewClip(Clip clip, int index) {
this.clips.add(index, clip);
notifyItemInserted(index);
}
Adding to clips(MainActivity's) won't make a difference because your adapter has it own ArrayList to work with.

Related

How to get the item position in a ListView and GridView outside the adapter?

I'm trying to get a View position through his view hierarchy.
When I have a RecyclerView, for get the current view position I do:
if(view.getParent() instanceof RecyclerView){
RecyclerView rv = (RecyclerView)view.getParent();
if(rv.getLayoutManager()!=null) {
position = rv.getLayoutManager().getPosition(view);
}
}
But when a ListView or GridView appears, I'm not able to get a Layout Manager to get the position of the view. The idea is to make it in a generic way, without knowing the Custom Adapter the view has.
I have tried to get the position through the ListView and GridView adapter but I dont see any method that do that.
Someone can help me?
Thank you a lot!
Create interface for get position for outside adapter class
here is adapter code:
public class ReportMediaAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<File> reportMediaList = new ArrayList<>();
private Context context;
private int selectedPos = -1;
private OnRemoveImage onRemoveImage;
public ReportMediaAdapter(Context context, ArrayList<File> reportMediaList, OnRemoveImage onRemoveImage) {
this.reportMediaList = reportMediaList;
this.onRemoveImage = onRemoveImage;
this.context = context;
}
**public interface OnRemoveImage {
void onRemove(int pos);
}**
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView iv_image, iv_remove;
public MyViewHolder(View itemView) {
super(itemView);
iv_image = itemView.findViewById(R.id.iv_image);
iv_remove = itemView.findViewById(R.id.iv_remove);
}
}
#Override
public int getItemCount() {
return reportMediaList.size()-1;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_media, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
try {
MyViewHolder menuItemHolder = (MyViewHolder) holder;
CommonMethods.loadImage(context, reportMediaList.get(position), menuItemHolder.iv_image);
menuItemHolder.iv_remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
**onRemoveImage.onRemove(position);**
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is activity code:
#Override
public void onRemove(int pos) {
// use adapter position
}
I have found a solution:
if(view.getParent() instanceof ViewGroup) {
position = ((ViewGroup)view.getParent()).indexOfChild(view);
}

how to make the progress bar invisible in recyclerview

There is a list of pictures made through RecyclerView. When you click on a picture while it is being transferred to the next activity, a ProgressBar should be displayed. When there is a return to the activity of the image selection, the ProgressBar also remains visible, although it must be hidden.
As I did below, the progress bar becomes invisible only in the first image, but in the rest it does not work. I can’t understand why
in my project there are such classes as:
interface
public interface ImageOnC {
void onClick(int position);
}
ImageViewHolder
public class ImageViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
private ImageOnC imageOnC;
public ImageButton imageButton;
public ProgressBar progressBar;
public void setImageOnC(ImageOnC imageOnC) {
this.imageOnC = imageOnC;
}
public ImageViewHolder(#NonNull final View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image_outline);
progressBar = itemView.findViewById(R.id.progr);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageOnC.onClick(getAdapterPosition());
progressBar.setVisibility(View.VISIBLE);
}
});
}
}
ImageAdabter
public class ImageAdabter extends RecyclerView.Adapter<ImageViewHolder> {
private Context mContext;
private List<Integer> listImages;
public ImageAdabter(Context mContext){
this.mContext = mContext;
this.listImages = getImages();
}
private List<Integer> getImages() {
List<Integer> results = new ArrayList<>();
results.add(R.drawable.outline1);
results.add(R.drawable.outline2);
results.add(R.drawable.outline3);
results.add(R.drawable.outline4);
results.add(R.drawable.outline5);
results.add(R.drawable.outline6);
results.add(R.drawable.outline7);
results.add(R.drawable.outline8);
results.add(R.drawable.outline9);
results.add(R.drawable.outline10);
return results;
}
#NonNull
#Override
public ImageViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_images,parent,false);
return new ImageViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ImageViewHolder holder, final int position) {
holder.imageView.setImageResource( listImages.get(position));
holder.setImageOnC(new ImageOnC() {
#Override
public void onClick(int position) {
Common.PICTURE_SELECTED = listImages.get(position);
mContext.startActivity(new Intent(mContext, Colorful.class));
}
});
#Override
public void onBindViewHolder(#NonNull ImageViewHolder holder, int position, List<Object>payload){
//if so, then the progress bar only works for the first image in recyclerview
if(!payload.isEmpty()){
if(payload.get(position) instanceof Integer)
holder.progressBar.setVisibility(View.GONE);
}
else super.onBindViewHolder(holder, position, payload);
}
#Override
public int getItemCount() {
return listImages.size();
}
}
I add this to activity
private void initView() {
recyclerView = findViewById(R.id.recycle_view_images);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adabter = new ImageAdabter(this);
recyclerView.setAdapter(adabter);
}
#Override
public void onResume() {
super.onResume();
if (adabter != null) {
adabter.notifyItemChanged(position, position);
}
}
in xml file use Progress bar visibility gone

How to add a recyclerview item dynamically when click a button in another activity?

I have a recyclerview in ShoppingCartActivity and a button in ProductDetailActivity. I want to send some data to ShoppingCartActivity when a button clicked in ProductDetailActivity and display them in recyclerview item that creates dynamically in ShoppingCartActivity.
I added addData method to recyclerview Adapter but it doesn't work and app crashes.
shop_btn = findViewById(R.id.add_to_shopping_cart);
shop_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent addToCart = new Intent(ProductDetailActivity.this, ShoppingCartActivity.class);
startActivity(addToCart);
}
});
//HERE IS MY RECYCLERVIEW ADAPTER
public class RecyclerViewAdapter_ShoppingCart extends RecyclerView.Adapter<RecyclerViewAdapter_ShoppingCart.MyViewHolder> {
private Context context;
List<CartItems> cartItemsList;
public RecyclerViewAdapter_ShoppingCart(Context context, List<CartItems> cartItemsList) {
this.context = context;
this.cartItemsList = cartItemsList;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater layoutInflater = LayoutInflater.from(context);
view = layoutInflater.inflate(R.layout.card_cart, parent, false);
return new MyViewHolder(view);
}
#NonNull
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.cart_title.setText(cartItemsList.get(position).getTitle());
holder.cart_price.setText(cartItemsList.get(position).getPrice());
Picasso.get().load(cartItemsList.get(position).getImageUrl()).into(holder.cart_img);
}
#Override
public int getItemCount() {
return cartItemsList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView cart_title, cart_price;
ImageView cart_img;
public MyViewHolder(View itemView) {
super(itemView);
cart_title = itemView.findViewById(R.id.cart_title);
cart_price = itemView.findViewById(R.id.cart_price);
//cart_delete = itemView.findViewById(R.id.cart_delete);
cart_img = itemView.findViewById(R.id.cart_image);
}
}
public void addItem(List<CartItems> cartItems) {
CartItems newValue = new CartItems();
newValue.setTitle("123");
newValue.setPrice("123");
newValue.setImageUrl("");
cartItems.add(newValue);
notifyDataSetChanged();
}
}
My goal is adding recyclerview items dynamically to ShoppingCartActivity when a button clicked in ProductDetailActivity but app crashes.

How to call an Interstitial by clicking on an item in the list that goes through an Adapter?

I need to call an Interstitial in this Activity by clicking on an item in the list that comes from my Adapter.
public class SoundRecyclerAdapter extends RecyclerView.Adapter<SoundRecyclerAdapter.SoundViewHolder> {
private final ArrayList<SoundObject> soundObjects;
SoundRecyclerAdapter(ArrayList<SoundObject> soundObjects) {
this.soundObjects = soundObjects;
}
#NonNull
#Override
public SoundViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.sound_item, parent, false);
return new SoundViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull SoundViewHolder holder, int position) {
final SoundObject object = soundObjects.get(position);
final Integer soundID = object.getItemID();
holder.itemTextView.setText(object.getItemName());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// I tried calling the interstitial here, but to no avail
EventHandlerClass.startMediaPlayer(v, soundID);
}
});
// Handle actions when the user presses a sound button
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
EventHandlerClass.popupManager(v, object);
return true;
}
});
}
#Override
public int getItemCount() {
return soundObjects.size();
}
class SoundViewHolder extends RecyclerView.ViewHolder {
final TextView itemTextView;
SoundViewHolder(View itemView) {
super(itemView);
itemTextView = itemView.findViewById(R.id.textViewItem);
}
}
}
Pass context as parameter of adapter's constructor:
private Context context;
SoundRecyclerAdapter(Context context, ArrayList<SoundObject> soundObjects) {
this.soundObjects = soundObjects;
this.context = context;
}
and use it in click handler
Use this code in the setOnClickListener() method:
mInterstitialAd = new InterstitialAd(SoundRecyclerAdapter.this);
Then add the adrequests and load the ad.

How to add onClick event on Android recycler view items?

Android Recycler View OnClick event is not working in the code. I can see the Recycler view grid but when I am clicking on one item nothing is happening.
Here is my code:
public class StaggeredGridAdapter extends RecyclerView.Adapter<StaggeredGridAdapter.StaggeredGridView> {
private Context context;
private List<Warehouse> warehouses = new ArrayList<Warehouse>();
int size;
public StaggeredGridAdapter(Context context) {
this.context = context;
}
public void addItems(List<Warehouse> response) {
size = response.size();
warehouses = response;
}
#Override
public StaggeredGridView onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
StaggeredGridView staggeredGridView = new StaggeredGridView(layoutView);
return staggeredGridView;
}
#Override
public void onBindViewHolder(StaggeredGridView holder, int position) {
holder.textView.setText(warehouses.get(position).getFace());
}
#Override
public int getItemCount() {
return size;
}
class StaggeredGridView extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView textView;
public StaggeredGridView(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.img_name);
}
#Override
public void onClick(View v) {
Toast.makeText(context, "clicked", Toast.LENGTH_SHORT).show();
}
}
}
I inherited inner class i.e. StaggeredGridView with Views.OnClickListner and debug point is not reaching to StaggeredGridView.OnClick method. There is no exception in ADB logs.
What I am doing wrong here?
You need to do this simple thing and it will start working with you
itemView.setOnClickListener(this)
//add this
public StaggeredGridView(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.img_name);
staggeredGridView.setOnClickListener(this)
}

Categories