Reputation: 60
I'm using a RecyclerView to display a list of cards. On pressing a certain button on a card, the item associated with it is supposed to be removed from the database as well as the RecyclerView, therefore displaying a freshly updated RecyclerView with the remaining items.
Now the issue is that when I remove an item by pressing the button, the Firebase ValueListener is triggered and a fresh RecyclerView is to be generated, but instead, each of the remaining items is duplicated. This gives me a RecyclerView which has two of each item.
The ValueEventListener code block
usersRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
discoverPeopleList = new ArrayList<>();
discoverPeopleRecyclerAdapter = new DiscoverPeopleRecyclerAdapter(getContext(), discoverPeopleList);
discoverPeople.setAdapter(discoverPeopleRecyclerAdapter);
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
final java.lang.String
key = snapshot.getKey();
DatabaseReference ref = database.getReference().child("users").child(key).child("followers");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
boolean isBeingFollowed = false;
for (DataSnapshot ss : dataSnapshot.getChildren()){
if (ss.getKey().equals(mAuth.getCurrentUser().getUid())){
isBeingFollowed = true;
}
}
if (!isBeingFollowed && !key.equals(mAuth.getCurrentUser().getUid())){
Log.v("Add", "One key added");
discoverPeopleList.add(key);
discoverPeopleRecyclerAdapter.notifyDataSetChanged();
}
}else if (!key.equals(mAuth.getCurrentUser().getUid())){
Log.v("Add", "One key added");
discoverPeopleList.add(key);
discoverPeopleRecyclerAdapter.notifyDataSetChanged();
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
discoverPeopleProgressBar.setVisibility(View.GONE);
discoverSessionsProgressBar.setVisibility(View.GONE);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
The OnClickListener code block in the adapter class(This is where the item is removed from the database)
holder.followBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (holder.followBtn.getText().equals("follow")){
DatabaseReference followers = FirebaseDatabase.getInstance().getReference().child("users").child(userKey).child("followers");
followers.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(FirebaseAuth.getInstance().getCurrentUser().getUid());
FirebaseDatabase.getInstance().getReference().child("notificationRequests").child("username").setValue(userKey);
FirebaseDatabase.getInstance().getReference().child("notificationRequests").child("message").setValue(FirebaseAuth.getInstance().getCurrentUser().getUid() + " followed you");
DatabaseReference following = FirebaseDatabase.getInstance().getReference().child("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("following");
following.child(userKey).setValue(userKey);
holder.followBtn.setText("following");
}else{
DatabaseReference followers = FirebaseDatabase.getInstance().getReference().child("users").child(userKey).child("followers");
followers.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).removeValue();
DatabaseReference following = FirebaseDatabase.getInstance().getReference().child("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("following");
following.child(userKey).removeValue();
holder.followBtn.setText("follow");
}
}
});
The Layout XML
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#303030"
tools:context="com.veloxima.sporthub.LiveDiscover">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
...
<android.support.v7.widget.RecyclerView
android:id="@+id/discover_people_recyclerVIew"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"></android.support.v7.widget.RecyclerView>
...
</LinearLayout>
</ScrollView>
Edit: I have confirmed that the ArrayList does indeed get cleared. The RecyclerView, on the other hand, is still messing up.
Upvotes: 0
Views: 114
Reputation: 598728
When anything changes under usersRef
, you'll get a complete new snapshot of the data under that location. So your code ends up adding all users (except for the one that was removed) to the discoverPeopleList
again.
To stop this from happening, you'll need to clear discoverPeopleList
before adding the new data:
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
boolean isBeingFollowed = false;
discoverPeopleList.clear();
for (DataSnapshot ss : dataSnapshot.getChildren()){
if (ss.getKey().equals(mAuth.getCurrentUser().getUid())){
isBeingFollowed = true;
}
}
if (!isBeingFollowed && !key.equals(mAuth.getCurrentUser().getUid())){
Log.v("Add", "One key added");
discoverPeopleList.add(key);
discoverPeopleRecyclerAdapter.notifyDataSetChanged();
}
}else if (!key.equals(mAuth.getCurrentUser().getUid())){
Log.v("Add", "One key added");
discoverPeopleList.add(key);
discoverPeopleRecyclerAdapter.notifyDataSetChanged();
}
This will work, but result in a complete redraw of the RecyclerView. To allow you to more granularly update the data, you should use addChildEventListener
. This listener allows you to respond to individual child events, such as onChildAdded
for adding users (including all the initial users) and onChildRemoved
for removing them.
To see an example of such an adapter, see this code in the FirebaseUI library: https://github.com/firebase/FirebaseUI-Android/blob/master/database/src/main/java/com/firebase/ui/database/FirebaseRecyclerAdapter.java
Upvotes: 1