Firebase recyclerViewAdpter not working properly - android

In my blog App in post detail Activity i added comments list with simple RecyclerView Adapter that was working fine but i am not able to add delete button for comment so moved to FireBase RecyclerView now i have lots of problems
it not updating in real time
when i comment that not pop out above the edit text layout when i close edit text box then it show my comments
when i write a comment and hit comment button it not show comment but when i writing the second comment on same time after writing three or four line the previous comment pop out and the edit text bot hide under the keyboard why this happening
Activity Code:
mCommentsRecycler.setLayoutManager(mlinearLayoutManager);
}
#Override
public void onStart() {
super.onStart();
// Add value event listener to the post
// [START post_value_event_listener]
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
Post post = dataSnapshot.getValue(Post.class);
// [START_EXCLUDE]
// mAuthorView.setText(post.author);
mTitleView.setText(post.title);
mBodyView.setText(post.body);
final String formImage = String.valueOf(post.postDetailPic);
// [END_EXCLUDE]
if (formImage.length() > 0) {
Picasso.with(getApplicationContext()).load(formImage)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(postPic, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
//Try again online if cache failed
Picasso.with(getApplicationContext())
.load(formImage)
//.error(R.drawable.ic_warning_black_24dp)
.into(postPic, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Log.v("Picasso", "Could not fetch image");
}
});
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// [START_EXCLUDE]
Toast.makeText(PostDetailActivity.this, "Failed to load post.",
Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
}
};
mPostReference.addValueEventListener(postListener);
// [END post_value_event_listener]
// Keep copy of post listener so we can remove it when app stops
mPostListener = postListener;
// Listen for comments
mAdapter = new CommentAdepter(Comment.class, CommentViewHolder.class, R.layout.item_comment, mCommentsReference, this);
mCommentsRecycler.setAdapter(mAdapter);
}
#Override
public void onStop() {
super.onStop();
// Remove post value event listener
if (mPostListener != null) {
mPostReference.removeEventListener(mPostListener);
}
// Clean up comments listener
mAdapter.cleanup();
}
#Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.button_post_comment) {
postComment();
}
}
private void postComment() {
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
assert mUser != null;
final String uid = mUser.getUid();
final DatabaseReference commentDb = FirebaseDatabase.getInstance().getReference().child("Users").child(uid);
commentDb.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user information
User user = dataSnapshot.getValue(User.class);
String authorName = user.name;
String commentUserPic = user.ProfilePic;
// Create new comment object
String commentText = mCommentField.getText().toString();
HashMap < String, Object > dateCreated; {
//Otherwise make a new object set to ServerValue.TIMESTAMP
dateCreated = new HashMap < String, Object > ();
dateCreated.put("timeStamp", ServerValue.TIMESTAMP);
}
HashMap < String, Boolean > commenter_id; {
commenter_id = new HashMap < String, Boolean > ();
commenter_id.put(getUid(), true);
}
Comment comment = new Comment(uid, authorName, commentText, commentUserPic, dateCreated, commenter_id);
// Push the comment, it will appear in the list
mCommentsReference.push().setValue(comment);
// Clear the field
mCommentField.setText(null);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private String getUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
private static class CommentViewHolder extends RecyclerView.ViewHolder {
public CommentViewHolder(View itemView) {
super(itemView);
authorView = (TextView) itemView.findViewById(R.id.comment_author);
bodyView = (TextView) itemView.findViewById(R.id.comment_body);
postingTime = (TextView) itemView.findViewById(R.id.comment_post_time);
rm_comment = (Button) itemView.findViewById(R.id.remove_comment);
}
public void setImage(String images) {
this.imageDp = images;
userPic = (ImageView) itemView.findViewById(R.id.comment_photo);
Picasso.with(context).load(imageDp).into(userPic);
}
void bindToPost(Comment comment, View.OnClickListener starClickListener) {
authorView.setText(comment.author);
bodyView.setText(comment.text);
setImage(comment.commentPic);
setViewValue(comment.getTimestampCreatedLong());
rm_comment.setOnClickListener(starClickListener);
}
}
private class CommentAdepter extends FirebaseRecyclerAdapter < Comment, CommentViewHolder > {
private Context mContext;
private List < String > mCommentIds = new ArrayList < > ();
private List < Comment > mComments = new ArrayList < > ();
private String mkey;
CommentAdepter(Class < Comment > CommentClass, Class < CommentViewHolder > viewHolderClass, int modelLayout, DatabaseReference ref, final Context context) {
super(CommentClass, modelLayout, viewHolderClass, mCommentsReference);
mContext = context;
// Create child event listener
// [START child_event_listener_recycler]
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
// A new comment has been added, add it to the displayed list
Comment comment = dataSnapshot.getValue(Comment.class);
// mkey = dataSnapshot.getKey();
// [START_EXCLUDE]
// Update RecyclerView
mCommentIds.add(dataSnapshot.getKey());
mComments.add(comment);
notifyItemInserted(mComments.size() - 1);
// [END_EXCLUDE]
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
// A comment has changed, use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
Comment newComment = dataSnapshot.getValue(Comment.class);
String commentKey = dataSnapshot.getKey();
// [START_EXCLUDE]
int commentIndex = mCommentIds.indexOf(commentKey);
if (commentIndex > -1) {
// Replace with the new data
mComments.set(commentIndex, newComment);
// Update the RecyclerView
notifyItemChanged(commentIndex);
} else {
Log.w(TAG, "onChildChanged:unknown_child:" + commentKey);
}
// [END_EXCLUDE]
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
// A comment has changed, use the key to determine if we are displaying this
// comment and if so remove it.
String commentKey = dataSnapshot.getKey();
// [START_EXCLUDE]
int commentIndex = mCommentIds.indexOf(commentKey);
if (commentIndex > -1) {
// Remove data from the list
mCommentIds.remove(commentIndex);
mComments.remove(commentIndex);
// Update the RecyclerView
notifyItemRemoved(commentIndex);
} else {
Log.w(TAG, "onChildRemoved:unknown_child:" + commentKey);
}
// [END_EXCLUDE]
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
// A comment has changed position, use the key to determine if we are
// displaying this comment and if so move it.
Comment movedComment = dataSnapshot.getValue(Comment.class);
String commentKey = dataSnapshot.getKey();
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w("PostDetailActivity", "postComments:onCancelled", databaseError.toException());
Toast.makeText(mContext, "Failed to load comments.",
Toast.LENGTH_SHORT).show();
}
};
ref.addChildEventListener(childEventListener);
// [END child_event_listener_recycler]
// Store reference to listener so it can be removed on app stop
}
#Override
public int getItemCount() {
return mComments.size();
}
#Override
protected void populateViewHolder(final CommentViewHolder viewHolder, final Comment model, final int position) {
final DatabaseReference commentRef = getRef(position);
final String commentKey = commentRef.getKey();
if (model.commenter_id.containsKey(gUid())) {
viewHolder.rm_comment.setVisibility(View.VISIBLE);
}
viewHolder.bindToPost(model, new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, "clicked " + commentKey, Toast.LENGTH_SHORT).show();
mCommentsReference.child(commentKey).removeValue();
}
});
}
}
private String gUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
}
if u need layout file please comment....

I added ability to delete an item in a FirebaseRecyclerAdapter and generally followed the advice in this post:
how to implement a SetOnItemClickListener FirebaseRecyclerViewAdapter
I used the first solution, adding an ImageView.setOnClickListener() call within populateViewHolder(). Its working fine for me.
I'm not quite sure what the #3 problem is above but I was having a problem whereby the data didn't get populated the first time it was called. I found my solution in this post, namely ensuring that the RecyclerView height was set to match_parent:
FirebaseRecyclerAdapter - populateViewHolder is not populating the data for first time it runs?

Related

Increment values in firebase realtime

There can be mutiple people on the app click a button that will Increment value in firebase and get that value back, but if each person clicks the button at the same time right now, they will get the same value, how do I Increment with each person getting a differnt value?
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("queue");
reference.child(queue_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
currentNum = (long) dataSnapshot.child("currentNumber").getValue();
++currentNum;
dataSnapshot.child("currentNumber").getRef().setValue(++currentNum);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
To prevent conflicts from multiple users updating the same node at (almost) the same time, you need to use a transaction. In your case that'd look something like:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("queue");
DatabaseReference numberRef = reference.child(queue_id).child("currentNumber");
numberRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Long value = mutableData.getValue(Long.class);
if (value == null) {
mutableData.setValue(1);
}
else {
mutableData.setValue(value+1);
}
return Transaction.success(mutableData);
}
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
Log.d(TAG, "runTransaction:onComplete:" + databaseError);
}
As per your code, you're incrementing the counter by 1 but you are not posting the same in the database. Use HashMap to update the data in your database when you modify it.
You can try the below code:
button.setOnClickListerner(new View.onClickListener() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("queue");
reference.child(queue_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
currentNum = (long) dataSnapshot.child("currentNumber").getValue();
long newValue = currentNum + 1;
HasMap<String, Object> hashMap = new HashMap<>();
hashMap.put ("currentNumber", newValue);
reference.child(queue_id).updateChildren(hashMap);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
};
Hope this works!
You can use method transactions. Refer to this link: https://firebase.google.com/docs/database/android/read-and-write#save_data_as_transactions"
private void onStarClicked(DatabaseReference postRef) {
postRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Post p = mutableData.getValue(Post.class);
if (p == null) {
return Transaction.success(mutableData);
}
if (p.stars.containsKey(getUid())) {
// Unstar the post and remove self from stars
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
} else {
// Star the post and add self to stars
p.starCount = p.starCount + 1;
p.stars.put(getUid(), true);
}
// Set value and report transaction success
mutableData.setValue(p);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
Log.d(TAG, "postTransaction:onComplete:" + databaseError);
}
});
}

How to check existed data in firebase?

I am using firebase database, but I am newbie with it. I am following this tutorial,
Now, my question is how can I check the email if it is already exist in the database? If email is already there data should not be add to db.
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView txtDetails;
private EditText inputName, inputEmail;
private Button btnSave;
private DatabaseReference mFirebaseDatabase;
private FirebaseDatabase mFirebaseInstance;
private String userId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Displaying toolbar icon
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setIcon(R.mipmap.ic_launcher);
txtDetails = (TextView) findViewById(R.id.txt_user);
inputName = (EditText) findViewById(R.id.name);
inputEmail = (EditText) findViewById(R.id.email);
btnSave = (Button) findViewById(R.id.btn_save);
mFirebaseInstance = FirebaseDatabase.getInstance();
// get reference to 'users' node
mFirebaseDatabase = mFirebaseInstance.getReference("users");
// store app title to 'app_title' node
mFirebaseInstance.getReference("app_title").setValue("Realtime");
// app_title change listener
mFirebaseInstance.getReference("app_title").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.e(TAG, "App title updated");
String appTitle = dataSnapshot.getValue(String.class);
// update toolbar title
getSupportActionBar().setTitle(appTitle);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read app title value.", error.toException());
}
});
// Save / update the user
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String name = inputName.getText().toString();
final String email = inputEmail.getText().toString();
// Check for already existed userId
if (TextUtils.isEmpty(userId)) {
createUser(name, email);
} else {
updateUser(name, email);
}
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Your Logic here
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
User mModel = eventSnapshot.getValue(User.class);
// Log.e("DATA" ,""+ mModel.getName());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
toggleButton();
}
// Changing button text
private void toggleButton() {
if (TextUtils.isEmpty(userId)) {
btnSave.setText("Save");
} else {
btnSave.setText("Update");
}
}
private void filter()
{
}
/**
* Creating new user node under 'users'
*/
private void createUser(String name, String email) {
// TODO
// In real apps this userId should be fetched
// by implementing firebase auth
if (TextUtils.isEmpty(userId)) {
userId = mFirebaseDatabase.push().getKey();
}
User user = new User(name, email);
mFirebaseDatabase.child(userId).setValue(user);
addUserChangeListener();
}
/**
* User data change listener
*/
private void addUserChangeListener() {
// User data change listener
mFirebaseDatabase.child(userId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
if(!dataSnapshot.child("users").child("email").exists())
{
Log.e(TAG, "User not exists");
}
else
{
Log.e(TAG, "User exists");
}
// Check for null
if (user == null) {
Log.e(TAG, "User data is null!");
return;
}
Log.e(TAG, "User data is changed!" + user.name + ", " + user.email);
// Display newly updated name and email
txtDetails.setText(user.name + ", " + user.email);
// clear edit text
inputEmail.setText("");
inputName.setText("");
toggleButton();
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read user", error.toException());
}
});
}
private void updateUser(String name, String email) {
// updating the user via child nodes
if (!TextUtils.isEmpty(name))
mFirebaseDatabase.child(userId).child("name").setValue(name);
if (!TextUtils.isEmpty(email))
mFirebaseDatabase.child(userId).child("email").setValue(email);
}
}
Inside ValueEventListener() check email address is exist or not
Try this
if(!dataSnapshot.child("users").child("email").exist)
then insert new value
If you are trying to create a rule for block user have 2 accounts with same email, you can use the rules inside firebase. There are rules ready for this.
Authentication -> Method -> botton functions.

Find out when does Query finish loading the latest added item

I have a function which write data into database
private void startCommenting() {
final String comment_val = meditComment.getText().toString().trim();
meditComment.setText("");
if (!TextUtils.isEmpty(comment_val)) {
mProgress.show();
final DatabaseReference newPost = mComment.child(post_key).push();
final String commentkey = newPost.getKey();
mUser.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String,Object> checkoutData=new HashMap<>();
checkoutData.put("time",ServerValue.TIMESTAMP);
newPost.setValue(checkoutData);
newPost.child("comment").setValue(comment_val);
newPost.child("uid").setValue(dataSnapshot.child("id").getValue());
newPost.child("blogpost").setValue(dataSnapshot.child("blogkey").getValue());
newPost.child("userimage").setValue(dataSnapshot.child("image").getValue());
newPost.child("username").setValue(dataSnapshot.child("name").getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
After this function was called, a Query was made to get the data which contains the right post_key in the child ("blogpost").
mpostComment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startCommenting();
mQueryCurrentComment = mComment.child(post_key).orderByChild("blogpost").equalTo(post_key);
mQueryCurrentComment.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String currentuserid;
String lastuserid = "";
String currentcommentuid;
for (DataSnapshot dsp : dataSnapshot.getChildren()) {
currentuserid = dsp.child("uid").getValue().toString();
Log.d(TAG, "user newid: " + currentuserid);
Log.d(TAG, "user oldid: " + lastuserid);
if (currentuserid.equals(lastuserid)) {
} else {
final DatabaseReference newCommentLike = mComment.child(currentuserid).push();
Map<String, Object> checkTime = new HashMap<>();
checkTime.put("time", ServerValue.TIMESTAMP);
newCommentLike.setValue(checkTime);
newCommentLike.child("location").setValue(location_key);
newCommentLike.child("category").setValue(category_key);
newCommentLike.child("pressed").setValue("false");
newCommentLike.child("message").setValue(" has also commented your post. ");
newCommentLike.child("blogpost").setValue(post_key);
newCommentLike.child(post_key).setValue(true);
}
lastuserid = currentuserid;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
However, the Query was triggered twice, one before the new item was added, another after new item was added, which looks like below:
How can I only perform the actions inside Query after the newest item was added and not twice? Any help is appreciated!

how to impliment delete and edit button in recyclerView using firebase

i am making a simple blog app using firebase as backend. in app i am showing comments list in post detail activity i want to implement edit and delete button in the front of every comment and want to visible it only if that comment write by the current user
this is my postDetailActivity
where should i need to implement the delete button
plz... help me if u need any other info comment....
updated to FirbaseRecyclerView but now delete button not working
public class PostDetailActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "PostDetailActivity";
public static final String EXTRA_POST_KEY = "post_key";
private DatabaseReference mPostReference;
private DatabaseReference mCommentsReference;
private ValueEventListener mPostListener;
protected String mPostKey;
private FirebaseRecyclerAdapter<Comment, CommentViewHolder> mAdapter;
private ImageView postPic;
private TextView mTitleView;
private TextView mBodyView;
private EditText mCommentField;
private Button mCommentButton;
public Button del_comment;
private RecyclerView mCommentsRecycler;
private LinearLayoutManager mlinearLayoutManager;
private String commentKey;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_detail);
// Get post key from intent
mPostKey = getIntent().getStringExtra(EXTRA_POST_KEY);
if (mPostKey == null) {
throw new IllegalArgumentException("Must pass EXTRA_POST_KEY");
}
// Initialize Database
mPostReference = FirebaseDatabase.getInstance().getReference()
.child("posts").child(mPostKey);
mCommentsReference = FirebaseDatabase.getInstance().getReference()
.child("post-comments");
// Initialize Views
// mAuthorView = (TextView) findViewById(R.id.post_author);
mTitleView = (TextView) findViewById(R.id.post_title);
mBodyView = (TextView) findViewById(R.id.post_body);
postPic = (ImageView) findViewById(R.id.form_details_image);
mCommentField = (EditText) findViewById(R.id.field_comment_text);
mCommentButton = (Button) findViewById(R.id.button_post_comment);
del_comment = (Button) findViewById(R.id.remove_comment);
mCommentsRecycler = (RecyclerView) findViewById(R.id.recycler_comments);
mCommentButton.setOnClickListener(this);
mCommentsRecycler.setHasFixedSize(true);
mlinearLayoutManager = new LinearLayoutManager(this);
mCommentsRecycler.setLayoutManager(mlinearLayoutManager);
}
private Query getcommentQuery(DatabaseReference mCommentsReference) {
return mCommentsReference.child(mPostKey);
}
#Override
public void onStart() {
super.onStart();
// Add value event listener to the post
// [START post_value_event_listener]
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
Post post = dataSnapshot.getValue(Post.class);
// [START_EXCLUDE]
// mAuthorView.setText(post.author);
mTitleView.setText(post.title);
mBodyView.setText(post.body);
final String formImage = String.valueOf(post.postDetailPic);
// [END_EXCLUDE]
if (formImage.length() > 0) {
Picasso.with(getApplicationContext()).load(formImage)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(postPic, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
//Try again online if cache failed
Picasso.with(getApplicationContext())
.load(formImage)
//.error(R.drawable.ic_warning_black_24dp)
.into(postPic, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Log.v("Picasso","Could not fetch image");
}
});
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// [START_EXCLUDE]
Toast.makeText(PostDetailActivity.this, "Failed to load post.",
Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
}
};
mPostReference.addValueEventListener(postListener);
// [END post_value_event_listener]
// Keep copy of post listener so we can remove it when app stops
mPostListener = postListener;
// Listen for comments
Query commentQuery = getcommentQuery(mCommentsReference);
mAdapter = new FirebaseRecyclerAdapter<Comment, CommentViewHolder>(Comment.class,R.layout.item_comment,
CommentViewHolder.class, commentQuery) {
#Override
protected void populateViewHolder(final CommentViewHolder viewHolder,final Comment model,final int position) {
final DatabaseReference commentRef = getRef(position);
commentKey = commentRef.getKey();
if (model.commenter_id.containsKey(gUid())){
viewHolder.rm_comment.setVisibility(View.VISIBLE);
}
viewHolder.bindToPost(model, new View.OnClickListener() {
#Override
public void onClick(View view) {
mCommentsReference.child(mPostKey).child(commentKey).removeValue();
}
});
}
};
mCommentsRecycler.setAdapter(mAdapter);
}
#Override
public void onStop() {
super.onStop();
// Remove post value event listener
if (mPostListener != null) {
mPostReference.removeEventListener(mPostListener);
}
// Clean up comments listener
mAdapter.cleanup();
}
#Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.button_post_comment) {
postComment();
}
}
private void postComment() {
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
assert mUser != null;
final String uid = mUser.getUid();
final DatabaseReference commentDb = FirebaseDatabase.getInstance().getReference().child("Users").child(uid);
commentDb.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user information
User user = dataSnapshot.getValue(User.class);
String authorName = user.name;
String commentUserPic = user.ProfilePic;
// Create new comment object
String commentText = mCommentField.getText().toString();
HashMap<String, Object> dateCreated;
{
//Otherwise make a new object set to ServerValue.TIMESTAMP
dateCreated = new HashMap<String, Object>();
dateCreated.put("timeStamp", ServerValue.TIMESTAMP);
}
HashMap<String,Boolean> commenter_id ;
{
commenter_id = new HashMap<String, Boolean>();
commenter_id.put(getUid(),true);
}
Comment comment = new Comment(uid, authorName, commentText, commentUserPic, dateCreated, commenter_id);
// Push the comment, it will appear in the list
mCommentsReference.push().setValue(comment);
// Clear the field
mCommentField.setText(null);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private String getUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
private Context mContext;
private DatabaseReference mDatabaseReference;
private ChildEventListener mChildEventListener;
private List<String> mCommentIds = new ArrayList<>();
private List<Comment> mComments = new ArrayList<>();
private String mkey;
// mContext = context;
// mDatabaseReference = ref;
// Create child event listener
// [START child_event_listener_recycler]
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
taskDeletion(dataSnapshot);
// A new comment has been added, add it to the displayed list
Comment comment = dataSnapshot.getValue(Comment.class);
mkey = dataSnapshot.getKey();
// [START_EXCLUDE]
// Update RecyclerView
mCommentIds.add(dataSnapshot.getKey());
mComments.add(comment);
mAdapter.notifyItemInserted(mComments.size() - 1);
// [END_EXCLUDE]
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
// A comment has changed, use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
Comment newComment = dataSnapshot.getValue(Comment.class);
String commentKey = dataSnapshot.getKey();
// [START_EXCLUDE]
int commentIndex = mCommentIds.indexOf(commentKey);
if (commentIndex > -1) {
// Replace with the new data
mComments.set(commentIndex, newComment);
// Update the RecyclerView
mAdapter.notifyItemChanged(commentIndex);
} else {
Log.w(TAG, "onChildChanged:unknown_child:" + commentKey);
}
// [END_EXCLUDE]
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
// A comment has changed, use the key to determine if we are displaying this
// comment and if so remove it.
String commentKey = dataSnapshot.getKey();
// [START_EXCLUDE]
int commentIndex = mCommentIds.indexOf(commentKey);
if (commentIndex > -1) {
// Remove data from the list
mCommentIds.remove(commentIndex);
mComments.remove(commentIndex);
// Update the RecyclerView
mAdapter.notifyItemRemoved(commentIndex);
} else {
Log.w(TAG, "onChildRemoved:unknown_child:" + commentKey);
}
// [END_EXCLUDE]
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
// A comment has changed position, use the key to determine if we are
// displaying this comment and if so move it.
Comment movedComment = dataSnapshot.getValue(Comment.class);
String commentKey = dataSnapshot.getKey();
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w("PostDetailActivity", "postComments:onCancelled", databaseError.toException());
Toast.makeText(mContext, "Failed to load comments.",
Toast.LENGTH_SHORT).show();
}
};
// ref.addChildEventListener(childEventListener);
// [END child_event_listener_recycler]
// Store reference to listener so it can be removed on app stop
// mChildEventListener = childEventListener;
private String gUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
}

Firebase - Sometimes value is not saving

Take a look at this GIF I recorded:
This is the database of a counter app I'm making. When a user increments, count gets added along with the count under
users:{
UID:{
count: x
}
}
However, if you can notice in the GIF, sometimes, the upper count gets incremented but the one under users doesn't. Here's the code I'm saving it with:
database = database.child("users").child(auth.getCurrentUser().getUid()).child("count");
final DatabaseReference finalDatabase = database;
database.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Get the latest int
final int[] i = {Integer.parseInt(button.getText().toString())};
//add to the user's count with an onFailureListener
finalDatabase.setValue(i[0]++).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG,"Adding user's count failed: " + e.getMessage());
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
//Now add to the original
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
database.child("Campaigns").child(key).child("count").setValue(i[0]++).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "Error: " + e.getMessage());
}
});
}
});
None of the onFailure methods get called. So why is this happening?
You can instead listen to the users node to count the total count. Here's an example
private Map<String, Long> userCount = new HashMap<>();
private Long totalCount = 0L;
private void addTotalCountListener() {
FirebaseDatabase.getInstance().getReference().child("users").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
User user = dataSnapshot.getValue(User.class);
userCount.put(dataSnapshot.getKey(), user.getCount);
totalCount += user.getCount();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
// subtract the total count with the previous count
totalCount -= userCount.get(dataSnapshot.getKey());
// then add the new count
User user = dataSnapshot.getValue(User.class);
userCount.put(dataSnapshot.getKey(), user.getCount);
totalCount += user.getCount();
}
});
}

Categories

Resources