简体   繁体   中英

Android Firebase - Looping through and updating multiple paths/queries. Triggers garbage collection?

I'm having an issue when trying to update multiple paths after looping through the queries.

Here's a quick mock up of my database:

Subjects/
    - subjectId/
        - subjectName
        - subjectColor

Tasks/
    - taskId/
        - taskTitle
        - taskDesc
        - subjectId
        - subjectName
        - subjectColor

SubjectTasks/
    - taskId/
        - taskTitle
        - taskDesc
        - subjectId
        - subjectName
        - subjectColor

I have an activity in my app where users can edit the subjects' name and color. In order to update the subjectName and subjectColor properties of tasks with a subjectId value matching the one we edited I need to do a whole bunch of querying and looping through the Tasks and subjectTasks nodes. This is where the major performance hit happens (I think!)

It's this heavy looping and writing operation which I believe causes garbage collection to trigger, halting all threads, sending my app into an indeterminate loading screen.

GC触发 Garbage collection triggered when subject is edited and saved :(

After many hours studying the heap and the memory profiler in Android Studio I have no other ideas other than posting here. It's more annoying that this was found just days before release!

Here is the code snippet of the activity where the writing of the edited subject happens:

private void WriteEditedSubject(final String uid, final String subjectName, final String primaryColour, int swatchId){

    final DatabaseReference rootRef = mDatabase.getRef();

    SubjectItem editedSubject = new SubjectItem(subjectName, primaryColour, swatchId);
    editedSubject.setUid(subjectId);

    //create map of edited values
    Map<String, Object> subjectValues = editedSubject.toMap();

    //create map of updates to push
    final Map<String, Object> subjectUpdates = new HashMap<>();

    //update subjects node
    subjectUpdates.put("/subjects/" + uid + "/" + subjectId, subjectValues);

    //push updates
    rootRef.updateChildren(subjectUpdates);

    //todo: run a cloud function to update subject tasks and subjects using data from updated subject

    //update subject tasks node where tasks match subjectId
    mSubjectTasks.orderByChild("subjectId").equalTo(subjectId).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            //create map of updates to push
            Map<String, Object> subjectTaskUpdates = new HashMap<>();

            for(DataSnapshot taskShot : dataSnapshot.getChildren()){
                TaskItem task = taskShot.getValue(TaskItem.class);

                if(task != null) {
                    task.setSubjectName(subjectName);
                    task.setSubjectPrimaryColour(primaryColour);

                    Map<String, Object> taskValues = task.toMap();                     

                    subjectTaskUpdates.put("subjectTasks/" + uid + "/" + subjectId + "/" + task.getUid(), taskValues);
                }

            }

            rootRef.updateChildren(subjectTaskUpdates);

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    //update tasks node where tasks match subjectId
    mTasks.orderByChild("subjectId").equalTo(subjectId).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            //create map of updates to push
            Map<String, Object> taskUpdates = new HashMap<>();

            for(DataSnapshot taskShot : dataSnapshot.getChildren()){
                TaskItem task = taskShot.getValue(TaskItem.class);
                if(task !=  null) {
                    task.setSubjectName(subjectName);
                    task.setSubjectPrimaryColour(primaryColour);

                    Map<String, Object> taskValues = task.toMap();

                    taskUpdates.put("tasks/" + uid + "/" + task.getUid(), taskValues);

                }

            }

            rootRef.updateChildren(taskUpdates);

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

Is there a way this operation can be cleaned up and made more efficient? One idea I had was to write a cloud function that would trigger when the subject is edited but I'm determined to find out why this is happening.

Thanks for any help. Much appreciated!

It looks like what Bob Snyder pointed out was correct.

Replacing AddValueEventListener with AddListenerForSingleEvent fixed the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM