![](/img/trans.png)
[英]How to update Recyclerview new item added with smooth animation with firebase childEventListener?
[英]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
都有username
, major
和rating
。 我有兴趣获得这三个孩子的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.