Reputation: 193
i have a recycle view that contains a description of a comment and a vote count when i press up i need the count to increase this is how it looks like at the moment
but the problem is when i press up the vote does increase but until i close that fragment and reopen it it does not update
what actually happens is when i press up vote it makes an API call which does some logic and sends it over to android which has a number of the vote for that particular item which was being clicked or upvoted
how can i update that particular record so that i can see the change without reopening the view
code: CommentItem.java
public CommentItem(String id, String description, String voteCount)
{
this.id = id;
this.description= description;
this.voteCount = voteCount;
}
//getters and setters
CommentItemAdapter.java
...
private OnItemClickListener mlistener;
/*Interfaces*/
public interface OnItemClickListener{
void VoteUpClick(int position);
void VoteDownClick(int position);
...
}
...
CommentFragment.java
@Override
public void VoteUpClick(final int position) {
final CommentItem clickeedItem =
mitemList.get(position);
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
if (!error) {
String errorMsg = jObj.getString("msg");
Toast.makeText(getContext(), errorMsg,
Toast.LENGTH_SHORT).show();
} else {
String msg= jObj.getString("msg");
Toast.makeText(getContext(), msg,
Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("voteType", "up");
params.put("commentID", clickeedItem.getId().toString());
return params;
}
};
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
Upvotes: 4
Views: 203
Reputation: 3744
A lot of people here had a nice advice to use DiffUtils
. Thats quite a reasonable way to handle diffs inside dataset of RecycleView
.
The best way to perform it right now is to use ListAdapter
, which requires a DiffUtil.ItemCallback
or AsyncDifferConfig
. A really big pros of ListAdapter is that all differ logic is done on background, which in turns optimizes your UI.
Everything you need is to override this funs: areItemsTheSame()
and areContentsTheSame()
, additionally u have getChangePayload()
- for detailed info about the changed item.
Don't use the notifyDataSetChanged()
and other range update functions, all of that stuff is handled under-the-hood.
Yours case could be handled via different approaches. I prefer having an intermediate state which will notify user that something happens. So you can locally mark that comment with pending vote up, for example yellow arrow and when response is obtained from back-end you just need to refresh the data-list
and the ItemCallback
will do the diff trick for you. When response is retrieved and vote is applied it can be marked as green arrow. Those are just thoughts about the right flow.
In any case everything you need is to use the ListAdapter.sumbitList(newDataSet)
and the internal differ
of ListAdapter
will use ItemCallback to compare old and new list.
Upvotes: 1
Reputation: 1090
If I get it right, simply adapter.notifyDataSetChanged()
will update your list. But There is a better way, using DiffUtils
in recyclerView. That is, comparing old and new list, and updating only the changed item, not changing the whole data set.
Have a look at it out
https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00
Other approach, is to have the viewHolder reference from the Activity/Or Fragment, when onItemClick happens, by recyclerView.findViewHolderForAdapterPosition(position)
. Then change view by this view
Upvotes: 3