Bhaa Rizik
Bhaa Rizik

Reputation: 107

Insert data to firebase -Android - and check specific properties

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

Answers (1)

Frank van Puffelen
Frank van Puffelen

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

Related Questions