Skip to content Skip to sidebar Skip to footer

How Do I Update My Recyclerview Button State On Click After Alert Dialog Confirmation In Activity/fragment?

I have a pretty unique situation, where I have a button in a recyclerview, which upon click (initial state 'register'), passes an intent to a broadcast receiver in fragment or acti

Solution 1:

Are you updating the repo object based on user selected action on the dialog before calling notifyDatasetChanged()? Looks like the doRSVPEventApiCall() method does not update the list of items available to the adapter thus notifyDatasetChanged() has no effect.

Solution 2:

You can easily maintain an array to indicate the state of the buttons of each of your items in the RecyclerView. For example, let us assume there are two states of each button (i.e RSVP = 0, Cancel = 1). Now declare an array in your RecyclerView adapter like the following.

privateint[] stateArray; 

In the constructor of your adapter, initialize the array like the following. Let us assume your constructor looks like the following.

publicEventListAdapter(Context context, ArrayList<Event> eventList) {
    this.eventList = eventList; 
    stateArray = newint[eventList.size];
    initializeTheStateArray(eventList);
}

privatevoidinitializeTheStateArray(ArrayList<Event> eventList) {

    // Initialize the array so that we can keep track of the items which are being attended or not. for (int i = 0; i < eventList.size(); i++) {
        if(event.isAttending()) stateArray[i] = 1;
        else stateArray[i] = 0;
    }
}

Now in the onBindViewHolder function, set the text of the button based on the entry of the stateArray. This should look somewhat like the following.

if(stateArray[position] == 1) button.setText("Cancel"); // Because this item is already registerd elsebutton.setText("RSVP");

You need some additional function in your adapter so that you can update the stateArray on your button click or from an update from the API.

publicvoidupdateButtonState(int position, boolean isAttendening) {
    if(isAttending) stateArray[position] = 1;
    else stateArray[position] = 0;
    notifyDataSetChanged(); // Call the notifyDataSetChanged here to see the affect
}

And when you update the whole list of your adapter after an API call, do not forget the update the stateArray as well. I hope you have a function to update the event list in your adapter already. Modify the function like the following.

publicvoidupdateEventList(ArrayList<Event> eventList){
    this.eventList = eventList;
    stateArray = newint[eventList.size()];
    initializeTheStateArray(eventList);
}

Now you can call updateButtonState function of your adapter when the button is clicked. Modify the button click action in your rsvpButton.setOnClickListener.

You can also modify the onReceive function if necessary to get the expected output in your RecyclerView.

Hope this setup will help you to achieve the expected behavior that you want.

Last, but not least, in your onReceive function, you are immediately updating the RecyclerView when it will have no effect on the items of the RecyclerView because the network call is asynchronous and will take some time to fetch the data from the API. You might consider calling the updateEventList method from the onRSVPClick method when the data is available from the API call.

Hope that helps!

Solution 3:

I think that perhaps this might help:

  1. Set click listener on the button in onBindViewHolder().
  2. Inside your click listener call notifyItemChanged(position)
  3. Maintain some state in your adapter to handle the logic for when to change the buttons state, for instance, have a var in the onClick you can flag like shouldChangeState = true
  4. When on onBindViewHolder() is called again, check this state and bind as you would usually only handle this scenario and change TextView accordingly. button.setVisibility(..) or button.text = "My New Text"

Inside onBindViewholder :

 holder.myRow.setOnClickListener(v -> {
          notifyItemChanged(position) 
 }

Ok, so to handle your holder inside your onBindViewHolder (In Kotlin Sorry):

Create your view holder.

sealedclassMyListViewHolder(view: View) : RecyclerView.ViewHolder(view)

classMyListItemViewHolder(view: View) : MyListViewHolder(view) {
    val name: TextView = view.my_name
    val myDetail: TextView = view.my_detail
    val myOtherDetail: TextView = view.my_other_detail
}

In on create:

overridefunonCreateViewHolder(parent: ViewGroup, viewType: Int): MyListViewHolder {
        val inflater: LayoutInflater = LayoutInflater.from(parent.context)
        val view = inflater.inflate(R.layout.row_item, parent, false)
        val viewHolder = MyListItemViewHolder(view)

        with(view) {
            tag = viewHolder
        }
        return viewHolder
    }

Then in onBindViewHolder:

overridefunonBindViewHolder(itemHolder: MyListViewHolder, position: Int) {
        val holder = itemHolder as MyListItemViewHolder
        val currentInfo = myList[position]

        // Get your data from list to bind here.

        holder.name.text = // Text
        holder.myDetail.text = // Text
        holder.myOtherDetail.text = Text

        holder.setOnClickListener {
             // Other stuff, state, actions etc.
             notifyItemChanged(position)
        }
    }

Solution 4:

notifyDatasetChanged() should be called after the data set is actually changed. As Sudhanshu Gupta pointed out notifyDatasetChanged() is called at the wrong time (when the dialog button is clicked). Since your mEventListResponseList and mAllRSVPEventsList in the adapter are private the only way to change them is to call addItems() and addRSVPItems() methods. Clearly at the time of dialog button click, none of these methods are called indicating data set is not changed. So notifyDatasetChanged() has no effect.

it might take a few seconds to update. but regardless of whether it updates or not, is it possible to change the ui of the button in adapter to a different state (say cancel from rsvp) once alert appears and yes is clicked

No, because of the above reason.

And, when the response arrives it is discarded except for logging. Snippet from onRSVPClick() in the Presenter class.

.subscribe(response -> {
    if (!isViewAttached()) {
        return;
    }
    Log.d("rsvptest", "basic event id:" + response);

    getMvpView().hideLoading();

}

To see the change, you should somehow update mEventListResponseList and mAllRSVPEventsList in the adapter by exposing a suitable method and call it with the data from the arrived response. Also don't forget to call notifyDatasetChanged() in that method too.

Post a Comment for "How Do I Update My Recyclerview Button State On Click After Alert Dialog Confirmation In Activity/fragment?"