Reputation: 105
I've created a favourites page using a RecyclerView
with data saved on firebase. I'm attempting to delete an item from both firebase and the recyclerview in realtime. I can remove the item using
dataSnapshot.child(countries.get(position).getId()).getRef().removeValue();
countries.remove(position);
However, I can't remove the last item, but it deletes in firebase. I've tried different combinations of
notifyDataSetChanged();
notifyItemRemoved(position);
notifyItemRangeChanged(position, countries.size());
But with no luck so far, I can't see where I'm going wrong.
Populating recyclerview
Public class FavouritesFragment extends Fragment {
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
RecyclerView.Adapter adapter;
ArrayList<Country> countries;
private FirebaseAuth firebaseAuth;
private DatabaseReference databaseReference;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_favourites, container, false);
getActivity().setTitle("Favourites");
firebaseAuth = FirebaseAuth.getInstance();
databaseReference = FirebaseDatabase.getInstance().getReference();
FirebaseUser user = firebaseAuth.getCurrentUser();
String userID = user.getUid();
databaseReference = databaseReference.child("users").child(userID).child("Favourites");
recyclerView = view.findViewById(R.id.favourites_recycler);
countries = new ArrayList<>();
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
addFavourites();
return view;
}
public void addFavourites(){
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
Country c = ds.getValue(Country.class);
countries.add(c);
}
adapter = new FavouritesAdapter(countries);
recyclerView.setAdapter(adapter);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
Deleting from RecyclerView
in adapter class
public class FavouritesAdapter extends RecyclerView.Adapter<FavouritesAdapter.MyViewHolder>{
ArrayList<Country> countries;
private View view;
ImageBindingAdapter imageBindingAdapter = new ImageBindingAdapter();
RecyclerView recyclerView;
private int position;
private FirebaseDatabase firebaseDatabase;
private FirebaseAuth firebaseAuth;
private DatabaseReference databaseReference;
public FavouritesAdapter(ArrayList<Country> countries1){
countries = countries1;
}
@NonNull
@Override
public FavouritesAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.favourites, viewGroup, false);
recyclerView = view.findViewById(R.id.favourites_recycler);
firebaseAuth = FirebaseAuth.getInstance();
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference();
FirebaseUser user = firebaseAuth.getCurrentUser();
String userID = user.getUid();
databaseReference = databaseReference.child("users").child(userID).child("Favourites");
return new FavouritesAdapter.MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final FavouritesAdapter.MyViewHolder myViewHolder, final int i) {
myViewHolder.name.setText(countries.get(i).getName());
myViewHolder.snippet.setText(countries.get(i).getSnippet());
myViewHolder.popUp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popup = new PopupMenu(view.getContext(), view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.popup_menu, popup.getMenu());
popup.show();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_to_favs:
deleteFavourite();
break;
default:
return false;
}
return true;
}
});
}
});
@Override
public int getItemCount() {
return countries.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public ImageView popUp;
public MyViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.cityName);
popUp = itemView.findViewById(R.id.dotsPopUp);
}
}
public void deleteFavourite(){
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
String id = countries.get(position).getId();
if(dataSnapshot.exists() && dataSnapshot.child(id).exists()){
dataSnapshot.child(countries.get(position).getId()).getRef().removeValue();
countries.remove(position);
// notifyDataSetChanged();
// notifyItemRemoved(position);
// notifyItemRangeChanged(position, countries.size());
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
}); }
}
Upvotes: 1
Views: 105
Reputation: 40908
In your adapter you didn't set the position
to the position of the item you need to delete. So when the user hits the delete item in the popUp menu, you call deleteFavourite();
, but you need to set the class field position
before calling deleteFavourite()
.
So, in onBindViewHolder
, you need to assign the value of the second parameter to the position
, and it's better to pass it to deleteFavourite()
method as a paraemter like deleteFavourite(position)
:
@Override
public void onBindViewHolder(@NonNull final FavouritesAdapter.MyViewHolder myViewHolder, final int pos) {
....
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_to_favs:
deleteFavourite(pos);
break;
default:
return false;
}
return true;
}
});
Then change your deleteFavourite
to accept the new parameter, and notifyItemRemoved(position);
public void deleteFavourite(int pos){
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
String id = countries.get(pos).getId();
if(dataSnapshot.exists() && dataSnapshot.child(id).exists()){
dataSnapshot.child(countries.get(pos).getId()).getRef().removeValue();
countries.remove(pos);
notifyItemRemoved(pos);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
Upvotes: 1
Reputation: 4035
Do this to remove object from list, in deleteFavourite()
function:
..........
if(dataSnapshot.exists() && dataSnapshot.child(id).exists()){
dataSnapshot.child(countries.get(position).getId()).getRef().removeValue();
countries.remove(countries.get(position));
notifyDataSetChanged();
}
..............
Upvotes: 0