Reputation: 107
I need to insert lesson object to firebase, so I put here the onData change section of code. First of all I get data snapshot and insert the lessons that I have in firebase, after that I scan the List of Lessons and check: if the date and time exist in the firebase in any Lesson so I do something else I insert the lesson object to firebase . The main problem is : when I insert the details of the lesson and press add, the lesson enter to the firebase twice minimum, and if I try another insertion the program enter to infinite loop . will be happy for any help !
ArrayList<Lesson> existLesson=new ArrayList<>();
List<String> keys = new ArrayList<>();
int counter=0;
public void getLessons(DataSnapshot dataSnapshot){
//insert the lessons to "existLesson" arrayList
for (DataSnapshot keyNode : dataSnapshot.getChildren()) {
keys.add(keyNode.getKey());
Lesson lesson = keyNode.getValue(Lesson.class);
existLesson.add(lesson);
Log.i(tag, "data : " + lesson.getSubject());
}//for
}
int flag=1;
@Override
public void addLesson(final String subject, final String topic, final String date, final String time) {
mDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
getLessons(dataSnapshot);
//Check if date and time is busy
for (Lesson lessonToCheck : existLesson) {
if (lessonToCheck.getDate().equals(date) && lessonToCheck.getTime().equals(time)) {
flag = 0;
} else {
flag = 1;
}
}//for
if (flag == 0) {
Toast.makeText(LessonDetails.this, "date exist", Toast.LENGTH_SHORT).show();
// Check empty lessons
nearestLessons(existLesson, date, time);
} else {
if (flag == 1) {
String id = mDatabase.push().getKey();
Lesson lesson = new Lesson(subject, topic, date, time, id); //create lesson
Toast.makeText(LessonDetails.this,
subject + " - " + topic + " - " + date + " - " + time, Toast.LENGTH_SHORT).show();
mDatabase.child(id).setValue(lesson);
} //add lesson to DB
} //else
Log.i(tag,"end");
} //onDataChange
Upvotes: 0
Views: 52
Reputation: 599571
When you call you're adding a listener to the data at
. This listener will immediately read the data and call your onDataChange
, and then continues to listen for updates to the data.
For each update to the data, it calls your onDataChange
again. And since you're updating the data inside onDataChange
, this ends in an endless loop of setValue
->onDataChange
->setValue
->onDataChange
->...
To fix this, you'd typically use addListenerForSingleValueEvent
instead, as this only gets the value once and doesn't continue listening for changes.
So something like:
mDatabase.addForListenerValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
getLessons(dataSnapshot);
//Check if date and time is busy
for (Lesson lessonToCheck : existLesson) {
if (lessonToCheck.getDate().equals(date) && lessonToCheck.getTime().equals(time)) {
flag = 0;
} else {
flag = 1;
}
}//for
if (flag == 0) {
Toast.makeText(LessonDetails.this, "date exist", Toast.LENGTH_SHORT).show();
// Check empty lessons
nearestLessons(existLesson, date, time);
} else {
if (flag == 1) {
String id = mDatabase.push().getKey();
Lesson lesson = new Lesson(subject, topic, date, time, id); //create lesson
Toast.makeText(LessonDetails.this,
subject + " - " + topic + " - " + date + " - " + time, Toast.LENGTH_SHORT).show();
mDatabase.child(id).setValue(lesson);
} //add lesson to DB
} //else
Log.i(tag,"end");
} //onDataChange
})
Note that, since you're updating the data based on its current value, there's a chance that another user may be doing the same operation at almost the same time. If this can lead to conflicting updates in your use-case, consider using a transaction which combines the read and write from your code into a single (repeatable) operation.
Upvotes: 1