繁体   English   中英

使用Firebase ChildEventListener()更新ArrayAdapter

[英]Update ArrayAdapter with Firebase ChildEventListener()

我有一个像这样的Firebase数据库:

   {
  "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"
      }
    }
  }

有电影在reviews ,每movie都有usernamemajorrating 我有兴趣获得这三个孩子的PER用户名(三个孩子的父母)。 当用户查看我的应用程序的“电影详细信息”屏幕时,应该会发生这种情况-他们将看到其他用户留下的评论。 很简单。

我在更新自定义ReviewAdapter遇到了很大的困难。 目前,如果我们点击没有评论的电影,则可以毫无问题地添加它们。 我什至可以对我留下的评论进行修改。 唯一的问题是,提交的评论提交了两个评论-因此我最终重复了一次,直到我离开活动并回来。

我的问题可以在这里的录音中看到。 (没有声音)

我怀疑这与我使用Firebase的childEventListener() ,但仅在此问题上花费了4个小时以上之后,我无法弄清楚要更改的内容。

MovieDetailActivity.java

@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("<b>" + currentUser + "</b>"))); //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<String> usernames = new ArrayList<>();
                ArrayList<String> majors = new ArrayList<>();
                ArrayList<Double> ratings = new ArrayList<>();
                ArrayList<Review> reviews = new ArrayList<>();

                //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 < 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<String> usernames = new ArrayList<>();
                ArrayList<String> majors = new ArrayList<>();
                ArrayList<Double> ratings = new ArrayList<>();
                ArrayList<Review> reviews = new ArrayList<>();

                //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 < 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) {
            }
        });
    }

您将需要使用Push方法来拥有自己的唯一键。 您正在使用具有登录用户名的密钥。 您需要做这样的事情。

    {
  "reviews" : {
    "Star Trek Into Darkness" : {
      "-K3dksosdfify" : {
        "major" : "NONE",
        "rating" : 3.0,
        "username" : "j"
      }
    },
    "Star Wars" : {
      "-K3dksosdfify2" : {
        "major" : "Computer Science",
        "rating" : 3.5,
        "username" : "badabing"
      },
      "-K3dksosdfify4" : {
        "major" : "NONE",
        "rating" : 5.0,
        "username" : "j"
      }
    },
    "Star Wars: The Clone Wars" : {
      "-K3dksosdfify10" : {
        "major" : "NONE",
        "rating" : 3.0,
        "username" : "j"
      }
    },
    "Star Wars: The Force Awakens" : {
      "-K3dksosdfify11" : {
        "major" : "Computer Science",
        "rating" : 5.0,
        "username" : "badabing"
      },
      "-K3dksosdfify123" : {
        "major" : "NONE",
        "rating" : 3.0,
        "username" : "j"
      }
    }
  }

破折号是由FireBase生成的。 检查正式文件中的推送方法

现在,每次使用push时。 它将生成一个唯一键,因此不会影响其他Rating的属性。

像这样

Firebase ref = new Firebase(yourURLtoReviews);
ref.child(SELECTEDMOVIES);

Map<String, String> post1 = new HashMap<String, String>();
post1.put("major", "gracehop");
post1.put("rating", "3.0");
post1.put("username", "Hwoarang");

ref.push().setValue(post1);

现在,您不再需要关心密钥。 您所要做的就是ref.onChildAdded等等等等,用for循环将其初始化,您就完成了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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