我的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
都有username
,major
和rating
。我有兴趣获得这三个孩子的PER用户名(三个孩子的父母)。应该发生的是当用户观看"电影细节"我的应用程序的屏幕 - 他们将看到其他用户留下的评论。很简单。
我在更新自定义ReviewAdapter
方面遇到了很大困难。目前,如果我们点击一部没有评论的电影 - 我可以添加它们没问题。我甚至可以对我留下的评论进行编辑。唯一的问题是提交的评论提交了两篇评论 - 所以我最终会留下一份副本,直到我离开活动并回来。
My issue can be seen in this recording here. (No sound)
我怀疑它与我使用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) {
}
});
}
答案 0 :(得分:1)
您需要使用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"
}
}
}
Dashes是FireBase生成的。 Check the push method in the Official Document
现在每次使用推送。它将生成一个唯一键,因此其他评级的属性不会受到干扰。
这样的事情。
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 blah blah blah,it for for for循环,你已经完成了。