Lorek Bryanson Lorek Bryanson - 3 months ago 141
Android Question

Android - Update and delete data in Firebase database

I'm trying to update and delete data in Firebase database.

SectionDetails
model

public class SectionDetails {
private String sectionCode;
private String sectionSeats;
private String sectionKey;

public SectionDetails() {
}

public SectionDetails(String sectionCode, String sectionSeats) {
this.sectionCode = sectionCode;
this.sectionSeats = sectionSeats;
}

@Exclude
public String getSectionKey() {
return sectionKey;
}

public String getSectionCode() {
return sectionCode;
}

public String getSectionSeats() {
return sectionSeats;
}
}


FirebaseHelper
class

public class FirebaseHelper {
DatabaseReference db;
ArrayList<SectionDetails> sectionDetailsArrayList = new ArrayList<>();

public FirebaseHelper(DatabaseReference db) {
this.db = db;
}

private void fetchData(DataSnapshot dataSnapshot) {

SectionDetails sectionDetails = dataSnapshot.getValue(SectionDetails.class);
sectionDetailsArrayList.add(sectionDetails);

adapter.notifyDataSetChanged();
}

public ArrayList<SectionDetails> retrieve() {
db.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}

@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}

@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
adapter.notifyDataSetChanged();
}

@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {

}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});
return sectionDetailsArrayList;
}
}


CustomAdapter
class

public class CustomAdapter extends BaseAdapter {
DatabaseReference updateRef;
String key;
Context c;
ArrayList<SectionDetails> sectionDetailsArrayList;

public CustomAdapter(Context c, ArrayList<SectionDetails> sectionDetailsArrayList) {
this.c = c;
this.sectionDetailsArrayList = sectionDetailsArrayList;
}

@Override
public int getCount() {
return sectionDetailsArrayList.size();
}

@Override
public Object getItem(int position) {
return sectionDetailsArrayList.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

final SectionDetails sd = (SectionDetails) this.getItem(position);

updateRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_COURSES).child("sections");

convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Dialog d = new Dialog(CustomAdapter.this);
d.setContentView(R.layout.section_custom_dialog);

Button btnUpdate = (Button) d.findViewById(R.id.btnUpdate);
Button btnDelete = (Button) d.findViewById(R.id.btnDelete);

btnUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String code = "1B";
final String seats = "20";

updateRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
SectionDetails updateSD = snapshot.getValue(SectionDetails.class);
if (sd.getSectionCode().equals(updateSD.getSectionCode())) {
key = snapshot.getKey().toString();
}
}

SectionDetails newSD = new SectionDetails(code, seats);
updateRef.child(key).setValue(newSD);
}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});

}
});

btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

updateRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
SectionDetails deleteSD = snapshot.getValue(SectionDetails.class);
if (sd.getSectionCode().equals(deleteSD.getSectionCode())) {
updateSectionRef.child(snapshot.getKey().toString()).removeValue();
break;
}
}
adapter.notifyDataSetChanged();
}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});
}
});

d.show();
}
});


return convertView;
}
}


MainActivity
class

public class MainActivity extends AppCompatActivity {

DatabaseReference mRef;
FirebaseHelper helper;
CustomAdapter adapter;
ListView lvSectionsListOne;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

lvSectionsListOne = (ListView) findViewById(R.id.lvSectionsList);

mRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_COURSES).child("sections");
helper = new FirebaseHelper(mRef);

adapter = new CustomAdapter(this, helper.retrieve());
lvSectionsListOne.setAdapter(adapter);
}
}


The data is deleted from database as expected, but the data that gets deleted remains inside the
listview
. I added
adapter.notifyDataSetChanged()
but still the
listview
is not updating.

The data is also updated as expected, but when
update
button is clicked, the data is updated infinitely. I can see the
listview
as well as the database keep on appending the data, and can only be stopped by closing the app.

I have tried to move
SectionDetails newSD = new SectionDetails(code, seats)
and
updateRef.child(key).setValue(newSD)
to outside
for
loop but the data doesn't get updated because the key is not passed to the path outside the
for
loop.

Answer

I haven't thoroughly looked at all the code you posted and may not understand your processing completely. There are two things that might be causing some of the problems you described.

In FirebaseHelper, method onChildChanged() calls fetchData(), which adds the changed section details to the array list. Shouldn't you be updating the existing section details instead of adding them again? Also, in onChildRemoved(), the section details are not removed from the array list. Don't they need to be removed?

In CustomAdapter the click listeners for your buttons add anonymous ValueEventListeners. Because they are anonymous, you have no way of removing them when they are no longer needed. ValueEventListeners added with addValueEventListener() remain active until removed. If your goal is to get the data once, use addListenerForSingleValueEvent().

Comments