-1

thanks to stop by.

Not a long time ago someone explain to me that you should'nt store data in ViewHolder, I get why. But then it complicate something.

I want to remove a Row if user click on a button inside the row. So i need to access the adapter. But I can't store it on ViewHolder. What the way ?

EDIT : I am trying one solution but getTag return me null when I am in adapter

Here is my item and the binding :

public final class ItemViewMail extends RecyclerView.ViewHolder {

    private AppCompatImageButton cancelButton;


    public ItemViewMail(View itemView) {
        super(itemView);
        this.cancelButton = itemView.findViewById(R.id.profile_item_edit_email_cancel_image_button);
    }

    public void bind(Data data, View.OnClickListener deleteOnClickListener) {
        this.itemView.setTag(data);
       
        if (cancelButton != null) {
            cancelButton.setOnClickListener(deleteOnClickListener);
        }
    }

}

My adapter :

    private ArrayList<Data> rowDataArrayList;

    MyPVPViewAdapter(ArrayList<Data> rowDataArrayList) {
        this.rowDataArrayList = rowDataArrayList;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int itemType) {                    
    return new ItemViewMail(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.profile_item_edit_email, viewGroup ,false));
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder myViewHolder, int position) {
          ((ItemViewMail) myViewHolder).bind((Data) rowDataArrayList.get(position).getData(), onClickListener);
    }

    @Override
    public int getItemViewType(int position) {
        return rowDataArrayList.get(position).getType();
    }

    @Override
    public int getItemCount() {
        return rowDataArrayList.size();
    }

    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Data data = (Data) v.getTag();
        }
    };

}
Ryan M
  • 18,333
  • 31
  • 67
  • 74
TomJouin
  • 49
  • 10
  • try this blog - http://blog.inapptext.com/recyclerview-creating-dynamic-lists-and-grids-in-android-1/#responding_user_actions – Mohammed Atif Aug 22 '18 at 16:38

3 Answers3

0

You can remove the item from the adapter and notify it about the removed row and it will update smoothly with the removal. Also remove the item from your data source, seems like you're doing that already though.

mAdapter.getItems().remove(mPosition);
mAdapter.notifyItemRemoved(mPosition);
CodeSmith
  • 1,621
  • 1
  • 13
  • 31
0
data class MyItem(val name: String)

class MyViewHolder(itemView: View,
                   private val onRemoveClickListener: View.OnClickListener) : RecyclerView.ViewHolder(itemView) {

    fun bind(item: MyItem) {
        itemView.setOnClickListener(onRemoveClickListener)
        itemView.setTag(item)
        //todo: eg. itemView.name.setText(item.name)
    }
}

class MyRecyclerViewAdapter(private val onRemoveClickListener: View.OnClickListener): RecyclerView.Adapter<MyViewHolder>() {

    var items = listOf<MyItem>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.viewholder_my)
        return MyViewHolder(view, onRemoveClickListener)
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bind(items[position])
    }

}

Now you can create MyRecyclerViewAdapter inside your activity/fragment/etc and put onClickListener as a parameter.

class MyActivity: AppCompatActivity() {

    private lateinit var adapter: MyRecyclerViewAdapter 

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        adapter = MyRecyclerViewAdapter(View.OnClickListener { view ->
            val clickedItem = view.getTag() as MyItem
            adapter.items.remove(clickedItem)
            adapter.notifyDataSetChanged()
        })
    }
}
0

I want to remove a Row if user clic on a button inside the row. So i need to access adapter. But I can't store it on ViewHolder. What the way ?

The base implementation of RecyclerView.ViewHolder provides two methods you can call when you need access to position information: getAdapterPosition() and getLayoutPosition(). In your case, it sounds like you want the first one.

This lets you write code like this:

public void soSomethingOnClick() {
    int position = getAdapterPosition();

    if (position != RecyclerView.NO_POSITION) {
        myDataStructure.removeItemAt(position);
        myAdapter.notifyItemRemoved(position);
    }
}

Not a long time ago someone explain to me that you should'nt store data in ViewHolder, I get why. But then it complicate something.

I'm not sure what you heard, but storing information in a ViewHolder is totally fine. You have to be careful to make sure you always update whatever data you're storing so that it doesn't get out of sync when a ViewHolder is recycled, but very many ViewHolder implementations take express advantage of the fact that ViewHolders are a great place to save data.

Ben P.
  • 52,661
  • 6
  • 95
  • 123