Alvin John Babu
Alvin John Babu

Reputation: 2070

Recycler updates with duplicate values

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 enter image description here

it shows a duplicate of "Test 4" in 3rd and 4th position

enter image description here

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

Answers (2)

Zohaib Amir
Zohaib Amir

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

Chase Farmer
Chase Farmer

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

Related Questions