Reputation: 2070
I use wipe to delete method to delete a row, When i delete one row from the recycler list view it duplicates the value just below the one I had deleted.
If I delete "Test 3" from the list
it shows a duplicate of "Test 4" in 3rd and 4th position
my whole code used for list creation and deletion, can any one help me with this
public class fragmnetPendingAct extends Fragment {
private SwipeRefreshLayout refreshLayout;
private RecyclerView recyclerView;
ArrayList<String> activitynames;
FirebaseAuth mAuth;
View view;
List<modelclasspendingact> modelclasspendingactList = new ArrayList<>();
public fragmnetPendingAct() {
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_pendingactivity,container,false);
refreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_activitypend);
recyclerView = v.findViewById(R.id.recyclerviewpendingact);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
new ItemTouchHelper(itemtouchHelpercalback).attachToRecyclerView(recyclerView);
//listen to swipe horizontal
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// Get new Instance ID token
FirebaseUser mUser = mAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String token = task.getResult().getToken();
// Send token to your backend via HTTPS
getdatafromserver(token);
} else {
// Handle error -> task.getException();
Log.w(TAG, "getInstanceId failed second", task.getException());
}
}
});
refreshitems();
}
});
// Get new Instance ID token
FirebaseUser mUser = mAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String token = task.getResult().getToken();
Log.d(TAG, "onComplete lead: "+token);
// Send token to your backend via HTTPS
getdatafromserver(token);
} else {
// Handle error -> task.getException();
Log.w(TAG, "getInstanceId failed second", task.getException());
}
}
});
return v;
}
public void getdatafromserver(String token){
//new code using curl
String serverurl="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, serverurl,null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
Log.d(TAG, "activity list: "+response);
JSONObject alldata=response.getJSONObject("payload");
JSONArray assetaarray=alldata.getJSONArray("activities");
modelclasspendingactList.removeAll(modelclasspendingactList);
for(int i=0;i<assetaarray.length();i++)
{
JSONObject getactivity=assetaarray.getJSONObject(i);
String activityid = String.valueOf(getactivity.getInt("id"));
String activityname = getactivity.getString("title");
String activitydesc = getactivity.getString("description");
Log.d(TAG, "activity name: "+activityname);
//list crreation
modelclasspendingactList.add(new modelclasspendingact(activityname,activitydesc,activityid));
pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
){
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> headers=new HashMap<String,String>();
headers.put("Accept","*/*");
headers.put("Cache-Control","no-cache");
headers.put("cache-control","no-cache");
headers.put("token",token);
return headers;
}
};
singletonclasshttp.getInstance(getActivity()).addtorequestque(jsonObjectRequest);
}
private void refreshitems()
{
refreshLayout.setRefreshing(false);
}
//swipe function
ItemTouchHelper.SimpleCallback itemtouchHelpercalback = new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
Log.d(TAG, "onSwiped: "+modelclasspendingactList.get(viewHolder.getAdapterPosition()).getPendid());
Log.d(TAG, "onSwiped: position "+viewHolder.getAdapterPosition());
String activeid = modelclasspendingactList.get(viewHolder.getAdapterPosition()).getPendid();
// Get new Instance ID token
FirebaseUser mUser = mAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String token = task.getResult().getToken();
//send token and activity id to update function
markascompleted(activeid,token);
} else {
// Handle error -> task.getException();
Log.w(TAG, "getInstanceId failed second", task.getException());
}
}
});
Log.d(TAG, "onSwiped: position "+viewHolder.getAdapterPosition());
Log.d(TAG, "onSwiped: first list size "+modelclasspendingactList.size());
pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
modelclasspendingactList.remove(viewHolder.getAdapterPosition());
recyclerView.removeViewAt(viewHolder.getAdapterPosition());
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
// adapter.notifyItemRangeChanged(viewHolder.getAdapterPosition(), modelclasspendingactList.size());
// adapter.notifyDataSetChanged();
Log.d(TAG, "onSwiped: list size "+modelclasspendingactList.size());
// pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
// modelclasspendingactList.remove(viewHolder.getAdapterPosition());
// adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
}
};
private void markascompleted(String activeid,String token)
{
//send data to server
//curl function
String serverurl="xxxxxxxxxxxxxxxxxxxxxxx";
Map<String, Object> jsonParams = new ArrayMap<>();
jsonParams.put("id", activeid);
jsonParams.put("activityStatus", "COMPLETED");
jsonParams.put("targetEmployeeId", "1001");
jsonParams.put("score", "1");
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, serverurl,new JSONObject(jsonParams),
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d(TAG, "response: "+response);
try {
if (response.optBoolean("success")==true)
{
Toast.makeText(getActivity(), response.getString("message"),Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getActivity(),"Data Not Updated",Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
Toast.makeText(getActivity(),"Data Not Updated",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(),"Data Not Saved",Toast.LENGTH_SHORT).show();
error.printStackTrace();
}
}
){
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> headers=new HashMap<String,String>();
headers.put("Accept","*/*");
headers.put("Cache-Control","no-cache");
headers.put("Connection","keep-alive");
headers.put("Content-Type","application/json");
headers.put("cache-control","no-cache");
headers.put("token",token);
return headers;
}
};
singletonclasshttp.getInstance(getActivity()).addtorequestque(jsonObjectRequest);
}
}
Upvotes: 0
Views: 1119
Reputation: 3562
First I'll explain why you get this behavior, then we'll get to solution. In this code:
Problem #1:
pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
You are creating an adapter and pass it your current data. Note that the adapter will have its own copy of the list you passed in constructor.
modelclasspendingactList.remove(viewHolder.getAdapterPosition());
This list that you are removing Item from is different from the one you just sent in Adapter, so the Adapter still has old list. Then you call removed and adapter tries to update values but your removed item is still in the list that adapter has.
Solution:
Create A Function/Method in Adapter that removes the item from the list in adapter.
Problem #2 with Solution:
You are creating a new Adapter instance/object every time a view is swiped, it is unnecessary. Create the Adapter in class instead of function and instantiate it in onCreateView().
Upvotes: 1
Reputation: 113
A couple things.
First, the removeViewAt
is a function of RecyclerView.LayoutManager
. I imagine you meant to say recyclerView.LayoutManager.removeViewAt
.
Second, the call to removeViewAt
should not be necessary as RecyclerView
does this automatically when notifyItemRemoved
is called correctly.
Third, you do not need to re-bind the entire list when removing an item. You can remove the notifyItemRangeChanged
.
Fourth, you do not need to invalidate the entire adapter when removing an item either. You can remove notifyDataSetChanged
. In fact, this function should only be used as a last resort.
Initializing your RecyclerView
:
pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
RecyclerView recyclerView = view.findViewById(R.id.my_recycler_view);
recyclerView.adapter = adapter;
recyclerView.layoutManager = LinearLayoutManager(getActivity());
So your removal sequence should be
modelclasspendingactList.remove(viewHolder.getAdapterPosition());
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
Upvotes: 1