Android Firebase custom RecyclerView item click issue - android

I have to use custom RecyclerView because I don't want to update to list real time.
How do I get an id if I want to go into the details of the data? As in FirebaseRecyclerAdapter.
final String uid = getRef(position).getKey();
I added postId, my posts table, and I wrote the following code. But when click on the image, it goes to the last added image to the list. And when I click upVote, every item goes crazy and they click upVote too.
First, am I on the right track to update the list only when I want to? Second, why is everything going crazy?
PostAdapter
public PostRecyclerAdapter(Context context, Query query) {
this.context = context;
this.query = query;
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
posts.clear();
for (DataSnapshot data : dataSnapshot.getChildren()) {
posts.add(data.getValue(Post.class));
}
Collections.sort(posts, new Comparator<Post>() {
#Override
public int compare(Post o1, Post o2) {
Long a = o1.getCreatedDate();
Long b = o2.getCreatedDate();
if (a < b) {
return -1;
} else if (a == b) {
return 0;
} else {
return 1;
}
}
});
notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onBindViewHolder(final PostViewHolder viewHolder, int position) {
model = posts.get(position);
postId = model.getPostId();
viewHolder.setTitle(model.getTitle());
viewHolder.setImage(context, model.getImage());
viewHolder.setUpVote(postId);
viewHolder.imvImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, SinglePostActivity.class);
intent.putExtra(Enums.PostKeys.postId.getValue(), postId);
context.startActivity(intent);
}
});
viewHolder.imbUpVote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!checkAuthUser()) {
context.startActivity(new Intent(context, SignUpActivity.class));
return;
}
processVote = true;
Singleton.getDbPostDownVote(postId).child(postId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (processVote == true) {
if (dataSnapshot.hasChild(getUserId())) {
Singleton.getDbPostDownVote(postId).child(postId).child(getUserId()).removeValue();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Singleton.getDbPostUpVote(postId).child(postId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (processVote == true) {
if (dataSnapshot.hasChild(getUserId())) {
Singleton.getDbPostUpVote(postId).child(postId).child(getUserId()).removeValue();
processVote = false;
} else {
Singleton.getDbPostUpVote(postId).child(postId).child(getUserId()).setValue(0);
processVote = false;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
PostViewHolder:setUpVote
public void setUpVote(final String postId) {
Singleton.getDbPostUpVote(postId).child(postId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild(getUid())) {
imbUpVote.setImageResource(R.drawable.vote_up_active);
} else {
imbUpVote.setImageResource(R.drawable.vote_up_passive);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}

How do I get an id if I want to go into the details of the data?
Usually the id is a node in your db. As you can see in
final String uid = getRef(position).getKey();
getKey returns tha value of the node in db.
In your case to avoid sorting the list with comparator i would just structure the data like so:
20170111
title : some title
text : some text
20170112
title : some title
text : some text
This way data is going to be sorted by the nodes, which is the date, by Firebase. If you want to be more precise you can also add hours and minutes.
First, am I on the right track to update the list only when I want to?
No.
Calling addValueEventListener() is going to trigger the code inside the listener each time the value in your db changes. In other words, its realtime.
Use addListenerForSingleValueEvent() insted. It fires only once.
Second, why is everything going crazy?
Very important thing about onDataChange() is that it fires not only when the value changes but also the first time you set the listener. That is why everything is getting voted up when you click one item.

Related

How to hide current online user data from displaying in firebaseRecycler Adapter?

My app is displaying all the firebase data in firebaseRecycler Adapter. I want to exclude the data of current online user from displaying. e-g Ibad Ullah login to the app then his data must not be displayed in the recyclerview. I used Query orderByChild but it is hiding all users data. How can I achieve this? Thank You. Below is my code.
Dashboard Activity
if(fAuth.getCurrentUser() != null){
UID = FirebaseAuth.getInstance().getCurrentUser().getUid();
}
dRef.child(UID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
remainingClicks = String.valueOf(snapshot.child("clicksRemain").getValue(Integer.class));
showGigCount = String.valueOf(snapshot.child("showGigCount").getValue(Integer.class));
fiverrLink1 = (String) snapshot.child("gig").getValue();
String username = (String) snapshot.child("name").getValue();
clicks.setText(remainingClicks);
userName.setText(username);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
recyclerView = findViewById(R.id.dashboardRCV);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
LoadData();
}
private void LoadData() {
options = new FirebaseRecyclerOptions.Builder<ModelClass>()
.setQuery(dRef, ModelClass.class)
.build();
adapter = new FirebaseRecyclerAdapter<ModelClass, MyViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull MyViewHolder holder, int position, #NonNull ModelClass model) {
if (dRef.child(UID).child("clicksRemain").equals(0)){
zeroClicks.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
holder.previewLink.setURL(model.getGig(), new URLEmbeddedView.OnLoadURLListener() {
#Override
public void onLoadURLCompleted(URLEmbeddedData data) {
holder.previewLink.title(data.getTitle());
holder.previewLink.description(data.getDescription());
holder.previewLink.host(data.getHost());
holder.previewLink.thumbnail(data.getThumbnailURL());
holder.previewLink.favor(data.getFavorURL());
}
});
//This will hide the gig if its showGigCount becomes 0
Query query = dRef.orderByChild("showGigCount").equalTo(0);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()){
holder.previewLink.setVisibility(View.GONE);
}else{
holder.previewLink.setVisibility(View.VISIBLE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
};
query.addListenerForSingleValueEvent(valueEventListener);
holder.previewLink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// String profileLink = getRef(position).child(model.getGig()).toString();
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(model.getGig()));
startActivity(browserIntent);
}
});
There is no way to exclude a specific node from the Firebase database results, so the common way to do this is by hiding the node for the current user in the UI:
#Override
protected void onBindViewHolder(#NonNull MyViewHolder holder, int position, #NonNull ModelClass model) {
if (/* check whether this node is for the current */) {
holder.itemView.setVisibility(View.GONE);
}
else {
holder.itemView.setVisibility(View.VISIBLE);
}
holder.geglink.setText(model.getGig());
}
Also see:
How to hide an item from Recycler View on a particular condition?
You'll also either need to get the key from each node into your Java class, or you can keep a separate list of the keys.

How to hide empty rows in recycler view as i am using FirebaseRecyclerAdapter

I have a large list of posts in a social app. I am using FirebaseRecyclerAdapter that is fetching result directly from firebase and listens to any dataa changes made on firebase realtime database. I dont need all the posts, and when i put some condition on the posts, it shows the relevant posts correctly but those posts that are not fulfilling the condition the view shows at its place. Like its show empty list item if condition is not filled and if condition is fulfilled it show list item with data.
I want to remove listitems from list that doesnt fulfill the condition.
Below is my code. I have a string array that contains the id of business user is following. Post iteam contains a business id, now if post's business id matches with the id of business array post should be shown other wise not.
Query dbQuery = FirebaseDatabase.getInstance().getReference().child("new").child("BusinessPosts").orderByChild("timeStamp");
FirebaseRecyclerOptions<PostMC> options = new FirebaseRecyclerOptions.Builder<PostMC>()
.setQuery(dbQuery, PostMC.class).build();
firebasePostAdapter = new FirebaseRecyclerAdapter<PostMC, PostsViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull final PostsViewHolder holder, final int position, #NonNull final PostMC postMC) {
if (followingBusinessesList.contains(postMC.getBusinessID())) {
if (source.equals("BPF") || (source.equals("BHF"))) {
sharedByDBRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(mAuth.getCurrentUser().getUid()).hasChild(postMC.getPostID())) {
holder.shares.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_post_share_colored, 0, 0, 0);
} else {
holder.shares.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_post_share, 0, 0, 0);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
} else {
likedByDBRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(mAuth.getCurrentUser().getUid()).hasChild(postMC.getPostID())) {
holder.likes.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_liked, 0, 0, 0);
} else {
holder.likes.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_like, 0, 0, 0);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
holder.likes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mProcessLike = true;
final int postLikes = Integer.parseInt(String.valueOf(postMC.getPostLikes()));
likedByDBRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (mProcessLike) {
if (dataSnapshot.child(mAuth.getCurrentUser().getUid()).hasChild(postMC.getPostID())) {
businessPostsRef.child(postMC.getPostID()).child("postLikes").setValue("" + (postLikes - 1));
likedByDBRef.child(mAuth.getCurrentUser().getUid()).child(postMC.getPostID()).removeValue();
likedToDBRef.child(postMC.getPostID()).child(mAuth.getCurrentUser().getUid()).removeValue();
holder.likes.setText(postMC.getPostLikes());
mProcessLike = false;
} else {
businessPostsRef.child(postMC.getPostID()).child("postLikes").setValue("" + (postLikes + 1));
likedByDBRef.child(mAuth.getCurrentUser().getUid()).child(postMC.getPostID()).setValue("Liked");
likedToDBRef.child(postMC.getPostID()).child(mAuth.getCurrentUser().getUid()).setValue("Like");
holder.likes.setText(postMC.getPostLikes());
mProcessLike = false;
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
holder.userImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!mAuth.getCurrentUser().getUid().equals(postMC.getBusinessID())) {
Intent intent = new Intent(getActivity(), ViewBusinessProfileActivity.class);
intent.putExtra("businessID", postMC.getBusinessID());
startActivity(intent);
}
}
});
holder.profileLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!mAuth.getCurrentUser().getUid().equals(postMC.getBusinessID())) {
Intent intent = new Intent(getActivity(), ViewBusinessProfileActivity.class);
intent.putExtra("businessID", postMC.getBusinessID());
startActivity(intent);
}
}
});
Calendar calendar = Calendar.getInstance(Locale.getDefault());
calendar.setTimeInMillis(Long.parseLong(postMC.getPostTime()));
PrettyTime prettyTime = new PrettyTime(Locale.getDefault());
String ago = prettyTime.format(calendar);
holder.sub.setText(postMC.getPostMessage());
holder.time.setText(ago);
holder.shares.setText(postMC.getPostShares());
holder.likes.setText(postMC.getPostLikes());
holder.main.setText(postMC.getBusinessName());
Glide.with(getActivity()).load(postMC.getBusinessImageUrl()).into(holder.userImage);
if (postMC.getPostImage().equals("")) {
holder.postImage.setVisibility(View.GONE);
} else {
Glide.with(getActivity()).load(postMC.getPostImage()).into(holder.postImage);
}
} else {
}
}
#NonNull
#Override
public PostsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_single_post, viewGroup, false);
PostsViewHolder viewHolder = new PostsViewHolder(view);
return viewHolder;
}
};
userPostsRV.setAdapter(firebasePostAdapter);
firebasePostAdapter.startListening();
Businesss Data
Posts Data
Issue Image List Ite
recyclerViewImage
You can hide the entire view in the else part by setting the visibility to "GONE".
In your else part add the following.
if(followingBusinessesList.contains(postMC.getBusinessID())) {
...
}
else{
holder.itemView.setVisibility(View.GONE);
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
}

How to execute firebase function synchronously inside for loop?

I am retrieving data from firebase database inside for loop , but problem is that firebase functions are not execute synchronously , i know firebase functions are asynchronous . is there any solution for that ?
Code :-
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModelList.clear();
for(DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
Log.d("kkkk","1st");
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
peopleModelList.add(peopleModel);
Log.d("kkkk","2nd");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Log.d("kkkk","3rd");
}
iCallBackPeople.peopleAct(peopleModelList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Output :-
1st
3rd
2nd
But i want output like this
1st
2nd
3rd
Note :-
i searched , but never got any solution !
How to get data from Firebase Database in a loop?
Firebase addListenerForSingleValueEvent excute later in loop
I tried this but not worked for me, it is fill my list with last item !
public void listOfUsers(final ICallBackPeople iCallBackPeople) {
count=0;
//peopleModelList = new ArrayList<>();
sortedMap = new TreeMap<>();
// peopleModelList = new ArrayList<PeopleModel>(sortedMap.values());
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// peopleModelList.clear();
for(DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
//Object chatRoom = snapshot.getKey();
Log.d("kkkk","1st");
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
addItem(count,iCallBackPeople);
count++;
}
Log.d("kkkk","3rd");
}
Log.d("kkkk","end");
//iCallBackPeople.peopleAct(peopleModelList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void addItem(final int index, final ICallBackPeople iCallBackPeople) {
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
Log.d("kkkk","2nd");
sortedMap.put(index, peopleModel);
// sortedMap will sort your list by key (in this case, key is integer)
if(sortedMap.size()==2)
{
peopleModelList = new ArrayList<PeopleModel>(sortedMap.values());
iCallBackPeople.peopleAct(peopleModelList);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I tried this but not getting all of the item only getting list with last item in snapshot
public void listOfUsers(final ICallBackPeople iCallBackPeople) {
peopleModelList = new ArrayList<>();
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
PeopleModel peopleModel;
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModelList.clear();
for(final DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
getToken(new CallBackGetToken() {
#Override
public void token(String token) {
peopleModel.setRefresh_token(token);
Toast.makeText(context, token, Toast.LENGTH_SHORT).show();
peopleModelList.add(peopleModel);
//here i am checking my peopleModelList size is equal or not to snapshot
if(peopleModelList.size()==2)
iCallBackPeople.peopleAct(peopleModelList);
}
},peopleModel);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getToken(final CallBackGetToken callBackGetToken ,PeopleModel peopleModel) {
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
callBackGetToken.token((String)dataSnapshot.child("refresh_token").getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I think you should pass through an interface(create one and implement at this class). the method inside the interface should have a string as a parameter (it will receive your peopleModel.getChatWith() ) .
Inside your if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))you should request your interface.
I think is a solution for your asynchronously question.
Here is my solution:
int count =0;
SortedMap<Integer,PeopleModel> sortedMap;
private void set() {
count =0;
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModelList.clear();
sortedMap = new TreeMap<>();
for(DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
Log.d("kkkk","1st");
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
addItem(count);
count++;
}
Log.d("kkkk","3rd");
}
iCallBackPeople.peopleAct(peopleModelList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void addItem(final int index) {
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
Log.d("kkkk","2nd");
sortedMap.put(index, peopleModel);
// sortedMap will sort your list by key (in this case, key is integer)
// you can get peopleModelList = new ArrayList<>(sortedMap.values);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Maybe I'm over simplifying it, but I feel like you should just use simple recursion.
List<People> peopleList;
int currentIndex = 0
private void myFirebaseMethodAction(person){
registerListener.onCallbacks(new ValueListener(){
onDataChanged(){
person.addStufforDoStuff();
if(peopleList.size > currentIndex + 1){
myFirebaseMethodAction(peopleList.get(++currentIndex)
}
}
onFailed(){
//handle it
}
}
}
Does that make sense?
Just saying walk the list with an index, simple.
btw above is pseduo code, don't copy verbatim lol.

PopulateView function being fired many times before stopping

I'm using the following code to fill a list with data from a child within firebase database. The list is filled successfully, but I've got an issue: FirebaseListAdapter is being called multiple times before stopping, what does not occur when I use it in other activities.
One weird thing is that when I click a specific listView item, data from another item is passed through my openChat intent, what makes wrong data be retrieved to the chat activity I open. It seems that the calling multiple times thing is messing all the data.
Can someone point out what might be wrong with my code and/or what I must do to optimize it?
//database references
chatsRef = FirebaseDatabase.getInstance().getReference().child("chats").child(mAuth.getCurrentUser().getUid()); //the children of this are other users IDs
usersRef = FirebaseDatabase.getInstance().getReference().child("users");
////////// code for populateView I use within FirebaseListAdapter ///////////
FirebaseListAdapter<ChatUsers> firebaseListAdapter = new FirebaseListAdapter<ChatUsers>(getActivity(), ChatUsers.class, R.layout.item_user_listing, chatsRef) {
protected void populateView(View view, ChatUsers chatUsers, int position) {
TextView nameChatItemList = (TextView) view.findViewById(R.id.nameChatItemList);
id_other_user = getRef(position).getKey();
usersRef.child(id_other_user).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//for (DataSnapshot ds : dataSnapshot.getChildren())
Toast.makeText(mActivity, dataSnapshot.getValue().toString(), Toast.LENGTH_SHORT).show();
name = dataSnapshot.child("name").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent openChat= new Intent(getActivity().getApplicationContext(), Chat.class);
openChat.putExtra("iduser_chat", id_outro_usuario);
openChat.putExtra("name_user_chat", name);
startActivity(openChat);
}
});
}
}
EDIT Changes implemented as suggested by Farmaan
FirebaseListAdapter<ChatUsers> firebaseListAdapter = new FirebaseListAdapter<ChatUsers>(getActivity(), ChatUsers.class, R.layout.item_user_listing, ChatsRef) {
#Override
protected void populateView(View view, ChatUsers chatUsers, int position) {
TextView nomeImageChatItemList = (TextView) view.findViewById(R.id.nomeChatItemList);
String id_other_user = getRef(position).getKey();
usersRef.child(id_other_user).addListenerForSingleValue(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue().toString();
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
usersRef.child(id_other_user).addListenerForSingleValue(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue().toString();
Intent openChat = new Intent(getActivity().getApplicationContext(), Chat.class);
openChat.putExtra("iduser_chat", id_other_user);
openChat.putExtra("nameuser_chat", name);
startActivity(openChat);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
};
Since id_other_user and name are the class level field and you are updating it every time you populate the view.So the last view which is populated will decide the user id and the name.That's wrong with your code.
chatsRef = FirebaseDatabase.getInstance().getReference().child("chats").child(mAuth.getCurrentUser().getUid()); //the children of this are other users IDs
usersRef = FirebaseDatabase.getInstance().getReference().child("users");
////////// code for populateView I use within FirebaseListAdapter ///////////
protected void populateView (View view, ChatUsuarios chatUsuarios,int position){
TextView nameChatItemList = (TextView) view.findViewById(R.id.nameChatItemList);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id_other_user = getRef(position).getKey();
usersRef.child(id_other_user).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//for (DataSnapshot ds : dataSnapshot.getChildren())
String name = dataSnapshot.child("name").getValue().toString();
Intent openChat = new Intent(getActivity().getApplicationContext(), Chat.class);
openChat.putExtra("iduser_chat", id_other_user);
openChat.putExtra("name_user_chat", name);
startActivity(openChat);
Toast.makeText(mActivity, dataSnapshot.getValue().toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}

How to update user data Firebase?

I want to increment score by 1 when user clicks a button, but value of score is not updated. When I updated it manually from Firebase console it updates. I don't know what the problem is. Can anyone help me, please?
#Override
public void onClick(View view) {
if (view == add) {
score++;
databaseReference1 = databaseReference.child("score");
databaseReference1.setValue(String.valueOf(score));
databaseReference1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
textView_earning.setText(score + " ");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
You have to add the value event listener before changing the value.
#Override
public void onClick(View view) {
if (view == add) {
score++;
ref1 = ref.child("score");
ref1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
textView_earning.setText(score + " ");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
ref1.setValue(String.valueOf(score));
}
}
If you place addValueEventListener inside onClick(), you'll end up attaching one more listener into databaseReference1 every time the button clicked. It is not a best practice as you'll face more kind of problem if it is clicked multiple time.
You should place addValueEventListener somewhere else, like (not limited to) in activity's onCreate() method:
... onCreate(...) {
databaseReference1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
And place score variable where it is easily got, and update it inside onDataChange() (for this example, I place it on scoreValue:
private String scoreValue;
... onCreate(...) {
databaseReference1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
scoreValue = dataSnapshot.getValue(String.class)
}
...
And then inside onClick(), you just need to get scoreValue, increment it by 1, and save the value:
... onClick() {
if (view == add) {
scoreValue++;
databaseReference.child("score").setValue(scoreValue);
}
}
Then setValue(scoreValue) will update the value at the online database, and trigger onDataChange(). So don't worry if the value is changed online, scoreValue will always have updated value.
Hope this helps.
Note: all of this consider score value is at (your databaseReference
path)\score
you can use updateChildren for update single values.
Firebase ref = new Firebase(Constants.FIREBASE_URL);
HashMap<String, Object> hm = new HashMap<String, Object>();
hm.put("score", score++);
ref.child("YOUR_ROOT_NODE")
.updateChildren(hm);
thanks all for your answer,the problem is fixed,actually i make a stupid mistake as i do not set on click listener on my button

Categories

Resources