Update ArrayAdapter with Firebase ChildEventListener()
<p>I have a Firebase db structured like so:</p>

<pre><code>   {
  "reviews" : {
    "Star Trek Into Darkness" : {
      "j" : {
        "major" : "NONE",
        "rating" : 3.0,
        "username" : "j"
      }
    },
    "Star Wars" : {
      "badabing" : {
        "major" : "Computer Science",
        "rating" : 3.5,
        "username" : "badabing"
      },
      "j" : {
        "major" : "NONE",
        "rating" : 5.0,
        "username" : "j"
      }
    },
    "Star Wars: The Clone Wars" : {
      "j" : {
        "major" : "NONE",
        "rating" : 3.0,
        "username" : "j"
      }
    },
    "Star Wars: The Force Awakens" : {
      "badabing" : {
        "major" : "Computer Science",
        "rating" : 5.0,
        "username" : "badabing"
      },
      "j" : {
        "major" : "NONE",
        "rating" : 3.0,
        "username" : "j"
      }
    }
  }
</code></pre>

<p>There are movies under <code>reviews</code> and each <code>movie</code> has a <code>username</code>, <code>major</code>, and <code>rating</code>. I'm interested in getting those three children PER username (the parent of the three). What is supposed to be happening is when a user views the "Movie Details" screen of my app--they will see the reviews left by other users. Simple enough.</p>

<p>I'm having major difficulty with updating my custom <code>ReviewAdapter</code>. Currently, if we click on a movie that doesn't have a review--I can add them no problem. I can even submit an edit to the review I left. The only issue is that the submitted review submits two reviews--so I end up with a duplicate until I leave the activity and come back.</p>

<p><a href="https://streamable.com/sm1r" rel="nofollow">My issue can be seen in this recording here. (No sound)</a></p>

<p>I suspect it has something to do with the way I'm using Firebase's <code>childEventListener()</code>, but I couldn't figure out what to change after spending 4hrs+ on this issue alone.</p>

<p><strong>MovieDetailActivity.java</strong></p>

<pre><code>@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_movie_detail);
        ButterKnife.bind(this);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();

        if (bundle != null) {
            mMovieTitle = (String) bundle.get("title");
            mTempMovieTitle.setText(mMovieTitle);
        }

        setupReviews(); //calling it here
    }


public void leaveReview() {
        //get current username
        final String currentUser = SessionManager.getInstance(MovieDetailActivity.this).getLoggedInUsername();
        final MaterialDialog reviewDialog = new MaterialDialog.Builder(MovieDetailActivity.this)
                .title(leaveReviewTitle)
                .customView(R.layout.rating_movie_dialog, true)
                .theme(Theme.DARK)
                .positiveText(save)
                .negativeText(cancel)
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog reviewDialog, @NonNull DialogAction which) {
                        final RatingBar ratingBar = ButterKnife.findById(reviewDialog, R.id.rating_bar);
                        final double rating = ratingBar.getRating(); //get the rating

                        /*Get Major from Firebase, and also store the review while we're at it*/
                        mUserRef.child(currentUser).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                String major = dataSnapshot.child("major").getValue(String.class);
                                final Firebase reviewRef = mReviewRef.child(StringHelper.reviewHelper(mMovieTitle, currentUser));
                                reviewRef.child("username").setValue(currentUser);
                                reviewRef.child("major").setValue(major);
                                reviewRef.child("rating").setValue(rating);
                                setupReviews(); //and here
                            }
                            @Override
                            public void onCancelled(FirebaseError firebaseError) {
                            }
                        });
                    }
                }).build();
        //Leave review as {current_username}
        TextView reviewee = ButterKnife.findById(reviewDialog, R.id.reviewee);
        reviewee.append(" " + (Html.fromHtml("&lt;b&gt;" + currentUser + "&lt;/b&gt;"))); //bold the username text
        reviewDialog.show();
    }

    /**
     * *ATTEMPTS* to add and update the reviews list per each movie. It's hacky and I hate it.
     */
    private void setupReviews() {
        mReviewRef.child(mMovieTitle).addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String previousChildKey) {
                ArrayList&lt;String&gt; usernames = new ArrayList&lt;&gt;();
                ArrayList&lt;String&gt; majors = new ArrayList&lt;&gt;();
                ArrayList&lt;Double&gt; ratings = new ArrayList&lt;&gt;();
                ArrayList&lt;Review&gt; reviews = new ArrayList&lt;&gt;();

                //iterate through all of the reviews for the movie
                for (DataSnapshot child : dataSnapshot.getChildren()) {
                    switch(child.getKey()) {
                        case ("username"):
                            usernames.add(child.getValue(String.class));
                            break;
                        case ("major"):
                            majors.add(child.getValue(String.class));
                            break;
                        case ("rating"):
                            ratings.add(child.getValue(Double.class));
                            break;
                    }
                }

                if (!usernames.isEmpty()) { //only want to iterate if we're rating a movie that already has reviews
                    for (int i = 0; i &lt; usernames.size(); ++i) {
                        try {
                            reviews.add(new Review(usernames.get(i), majors.get(i), ratings.get(i)));
                        } catch (IndexOutOfBoundsException ioobe) {
                        }
                    }
                }

                if (mReviewAdapter == null) {
                    mReviewAdapter = new ReviewAdapter(MovieDetailActivity.this,
                            R.layout.review_list_item, reviews);
                    mMovieReviewsList.setAdapter(mReviewAdapter);
                } else {
                    try {
                        mReviewAdapter.addAll(reviews);
                        mMovieReviewsList.setAdapter(mReviewAdapter);
                        mReviewAdapter.notifyDataSetChanged();
                    } catch (NullPointerException npe) {
                    }
                }
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String previousChildKey) {
                ArrayList&lt;String&gt; usernames = new ArrayList&lt;&gt;();
                ArrayList&lt;String&gt; majors = new ArrayList&lt;&gt;();
                ArrayList&lt;Double&gt; ratings = new ArrayList&lt;&gt;();
                ArrayList&lt;Review&gt; reviews = new ArrayList&lt;&gt;();

                //iterate through all of the reviews for the movie
                for (DataSnapshot child : dataSnapshot.getChildren()) {
                    switch(child.getKey()) {
                        case ("username"):
                            usernames.add(child.getValue(String.class));
                            System.out.println("username " + child.getValue(String.class));
                            break;
                        case ("major"):
                            majors.add(child.getValue(String.class));
                            System.out.println("major " + child.getValue(String.class));
                            break;
                        case ("rating"):
                            ratings.add(child.getValue(Double.class));
                            break;
                    }
                }
                if (mReviewAdapter != null) {
                    mReviewAdapter.clear();
                }


                if (!usernames.isEmpty()) {
                    for (int i = 0; i &lt; usernames.size(); ++i) {
                        try { //I hate that checking if Usernames != empty isn't enough, and this is
                            //the only way I could get it to work...
                            reviews.add(new Review(usernames.get(i), majors.get(i), ratings.get(i)));
                        } catch (IndexOutOfBoundsException ioobe) {
                        }
                    }
                }

                if (mReviewAdapter == null) {
                    mReviewAdapter = new ReviewAdapter(MovieDetailActivity.this,
                            R.layout.review_list_item, reviews);
                    mMovieReviewsList.setAdapter(mReviewAdapter);
                } else {
                    try {
                        mReviewAdapter.addAll(reviews); //this might break it
                        mMovieReviewsList.setAdapter(mReviewAdapter);
                        mReviewAdapter.notifyDataSetChanged();
                    } catch (NullPointerException npe) {
                    }
                }
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
            }
            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String previousChildKey) {
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {
            }
        });
    }
</code></pre>