Jimmy
Jimmy

Reputation: 87

Duplicate item in recycler view, notifydatasetchanged is not working

I am running a transaction on click of a layout inside my adapter, but when I click the layout, the transaction runs successfully. But it creates another item inside my RecyclerView. I tried notifydatasetChanged() inside transaction but it creates an error:

CalledFromWrongThreadException: Only the original thread that created a view 
hierarchy can touch its views.

Then I tried putting notifyDataSetChanged() outside the transaction, but it's not working. Below is what I am doing:

holder.follow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                DatabaseReference mWorkDatabase = 
                FirebaseDatabase.getInstance().getReference()
               .child("WorkforWorkMen").child(work_id).child("follower");
                mWorkDatabase.runTransaction(new Transaction.Handler() {
                    @Override
                    public Transaction.Result doTransaction(MutableData 
                     mutableData) {
                        if(holder.followText.getText().equals("Follow")) {
                            holder.followText.setText("Following");
                            FirebaseAuth mAuth = FirebaseAuth.getInstance();
                            String current_user = 
                            mAuth.getCurrentUser().getUid();
                            DatabaseReference mFollowingDatabase = 
                            FirebaseDatabase.getInstance().getReference()
                  .child("WorkFollowing").child(current_user).child(work_id);
                            final Map fol = new HashMap();
                            fol.put("follower",work_id);
                            mFollowingDatabase.setValue(fol);
                            mutableData.setValue
                  (Integer.parseInt(mutableData.getValue().toString()) + 1);
                        }

                    else {
                            holder.followText.setText("Follow");
                            FirebaseAuth mAuth = FirebaseAuth.getInstance();
                            String current_user = 
                            mAuth.getCurrentUser().getUid();
                            DatabaseReference mFollowingDatabase = 
                            FirebaseDatabase.getInstance().getReference()
                  .child("WorkFollowing").child(current_user).child(work_id);
                            mFollowingDatabase.setValue(null);
                            mutableData.setValue(Integer
                           .parseInt(mutableData.getValue().toString()) - 1);
                        }

                        return Transaction.success(mutableData);
                    }
                    @Override
                    public void onComplete(DatabaseError databaseError, 
                    boolean b, DataSnapshot dataSnapshot) {
                        Toast.makeText(context,"error on complete"+ 
                  String.valueOf(databaseError), Toast.LENGTH_SHORT).show();
                        Log.i("eror here", "onComplete: 
                  "+String.valueOf(databaseError));
                    }
                });
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(context, "here", 
                          Toast.LENGTH_SHORT).show();
                        notifyDataSetChanged();
                    }
                });

            }
        });

i think when i add the data to my list the change in the value of followers cause it to add a new item, i am not sure though

 private void loadMessages(){
    if(keys.size() == 0){
        messagesList.clear(); 
        Toast.makeText(getContext(), " size zero no results found", 
    Toast.LENGTH_SHORT).show();
    }
    else {
        messagesList.clear();
        for (int i = 0; i < 5; i++) {
            if (i>=keys.size()){
                Toast.makeText(getContext(), "list is less than 5 item", 
            Toast.LENGTH_SHORT).show();
            }
            else {
                listPos = i;
                String id = keys.get(i);
                mWorkDatabase.child(id).addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        String messageKey = dataSnapshot.getKey();
                        NewWork message = dataSnapshot.getValue(NewWork.class);
                        itemPos++;
                        messagesList.add(message);
                        mAdapter.notifyDataSetChanged();
                        mRecyclerView2.scrollToPosition(messagesList.size() - 1);
                    }
                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                    }
                });
            }
        }
    }
}

Upvotes: 3

Views: 1248

Answers (2)

Alex Mamo
Alex Mamo

Reputation: 1

The Firebase database client, runs all network operations in a background thread. This means that you cannot create or modify views within that background thread. You can modify the UI only in the thread where those views were created. However, the thread in which you are allowed to make those changes is the main thread. So what you need to do is to get the following line of code out of the transaction.

notifyDataSetChanged();

Note: The entire view tree is single threaded. So, you must always be on the UI thread when calling any method on any view. If you are doing work on other threads and want to update the state of a view from that thread, you should use a Handler.

You can find much more here.

Upvotes: 1

Adeel Turk
Adeel Turk

Reputation: 907

You are calling notifyDataSetChanged() from background thread you need to call it from ui thread as follows

new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {

                notifyDataSetChanged();
            }
        });

Upvotes: 1

Related Questions