Android - Multiple queries for recyclerview (Firebase) - android

I am working with recylerviews and Firebase. I am using FirebaseUI to populate data to my recyclerview. I was wondering if it was possible to use two queries within my fragment. The query that should be executed should be dependent of if a node in the database exists.
Database Structure:
If the address child is present in the users node, my fragment should query the users node. If not it should query the routes node. Is this possible?
Basically here I am making by query which gets me all markers:
Query keyQuery = FirebaseDatabase.getInstance().getReference(sharedPreferences.getString("school", null)).child("markers");
recyclerView = (RecyclerView) rootView.findViewById(R.id.markerRecyclerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
FirebaseRecyclerOptions<FirebaseMarker> options = new FirebaseRecyclerOptions.Builder<FirebaseMarker>()
.setQuery(keyQuery, FirebaseMarker.class)
.build();
Inside my onBindViewHolder method I have an onClick on each item in the recyclerview. When the item is clicked, the user goes to a new activity. In this new activity the user can press a button which will add the address node under the users/userId node. What pressing that button means is that the user have chosen that marker. So I only want to show that marker information in the recyclerview and not every marker in the database.
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(),MainActivity.class);
intent.putExtra("databaseKey", key);
startActivity(intent);
}
});
I was thinking that: If a address and time node was inserted in the users node, I could just query this, which would make it easier.

This is possible, although I think you'd first need to check whether the user has selected a marker and then decide which query to attach to the FirebaseRecyclerAdapter.
To do that, it would likely be necessary to add a list of users that have selected each marker under the marker nodes, something like:
users
userId
selectedMarker // the ID of the marker selected by this user
...
markers
markerId
...
selectedUsers // list of user IDs that have selected this marker
Then, if the users node contains a selectedMarker value, you could use the below query to get all markers selected by this specific user:
Query query = FirebaseDatabase.getInstance().getReference()
.child(schoolId).child("markers")
.orderByChild("selectedUsers/"+userId).equalTo(true);
Where schoolId is from your sharedPreferences.getString("school", null) and userId is the currently logged in user's unique ID.
To check if the user has selected a marker, could be as simple as:
FirebaseDatabase.getInstance().getReference()
.child(schoolId).child("users").child(userId)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.child("selectedMarker").exists()) {
// Attach above query to FirebaseRecyclerAdapter
} else {
// Attach markers reference (no query) to FirebaseRecyclerAdapter
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
However, if you just want to display the user's single selected marker, it's likely that you don't need to use the RecyclerView at all, and could just use a separate view to display details about the user's selected marker.

Related

How to prevent my chats from duplicating themselves whenever someone sends a message in Android Studio firebase

I am designing a simple basic chat app using firebase real time database and i've designed everything well, however, i'm facing one sllight issue. My chats keep duplicating themselves on the inbox page (the page whrere the chats are laid out for a user to select which chat he wants to open and start talking).
I've attached an image of what i mean below.
Screenshot of the phone screen
The code i am using to get the chats and display them in the recycler view is given below. I have a directory called Conversations in my DB that saves a user's Id and under it, theres a child of each and every person he chats wit, under which is the last message and a seen boolean.
Database Structure
The code is given below
convoref = FirebaseDatabase.getInstance().getReference().child("Conversations").child(currentUid);
and then..
public void getConvoIds() {
convoref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for(DataSnapshot convo : dataSnapshot.getChildren()){
boolean isMessageSeen = false;
String lastMessage = "";
if(convo.child("seen").getValue() != null) {
isMessageSeen = (boolean) convo.child("seen").getValue();
}else{
Log.i("nolastseen", "location is null");
}
if(convo.child("lastMessage").getValue() != null) {
lastMessage = convo.child("lastMessage").getValue().toString();
}else{
Log.i("nolastMessage", "location is null");
}
Log.i ("the_convo_partner_key", convo.getKey());
Log.i ("lastseenmessage", lastMessage);
Log.i ("seenstate", String.valueOf(isMessageSeen));
FetchConvoInfo(convo.getKey(), isMessageSeen, lastMessage );
}
}
}
the fetch convo information functuion is below
public void FetchConvoInfo(final String key, final boolean isMessageSeen, final String lastMessage){
FirebaseDatabase.getInstance().getReference().child("Users").child(key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
boolean chatExists = false;
String username = "";
String thumbnail = "";
String chatPartner;
chatPartner = key;
if(dataSnapshot.child("username").exists()){
username = dataSnapshot.child("username").getValue().toString();
}
if(dataSnapshot.child("thumbnail").exists()){
thumbnail = dataSnapshot.child("thumbnail").getValue().toString();
}
ConvoClass obj= new ConvoClass(chatPartner, username, thumbnail, isMessageSeen, lastMessage);
resultConvos.add(obj);
mConvoAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Any help would be greatly appreciated. i cant seem to figure out why the chat duplicates.
In your onDataChanged method, you are going through every child of the dataSnapshot. Each child of the data snapshot indicates a particular conversation of that particular currentUid guy. So when you are going through every child of the dataSnapshot you are adding all its children to the listview or recyclerview(I don't know what you are using. But you are adding it to the adapter). So you are adding the old data again and again whenever some new data must be added. Hence-duplicate data.
There are two common solutions.
The first is naive method. Do what you are doing right now. But while adding an item (chat, you will call it in your case, I think) to the adapter, check if it is already present in the container resultConvos. That will prevent you from adding duplicate chats. I am sure it is obvious to you also why this method is inefficient. You are unnecessarily having to go through every conversation of a person. It takes O(n) time for just adding one item.
The second method is the recommended method. Remove all the code of ValueEventListener. Instead use ChildEventListener. I don't know if you are aware of it. Check this.
ChildEventListener has mainly 4 methods instead of onDataChanged. Among that, what you require here is onChildAdded. Just like your onDataChanged, it has one argument- a data snapshot. But this data snapshot contains only the newly added child, whereas the data snapshot in onDataChanged contains the whole data of the conversations of that particular user (that means the whole list). So using the data snapshot provided by onChildAdded you can directly add only that chat to the adapter, which takes O(1) time.
For more about ChildEventListener, read that link I attached

firebase realtime storage getting a specific value from all children

i am building a app using firebase that requires an admin page and in it i want to make a list of all the usernames of users registered in the system and i am using this code:
Usernames = new ArrayList<>();
usersdb = FirebaseDatabase.getInstance().getReference().child("Users");
usersdb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot user:dataSnapshot.getChildren()) {
Usernames.add(user.child("username").getValue().toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
adp = new ArrayAdapter<String>(context,android.R.layout.simple_list_item_1,Usernames);
lv.setAdapter(adp);
and for some reason nothing shows up in the list view in the end anyone knows why?
and my data structure looks like this:(the random letters are user uids)
Users
----sdfbsif
-----------email
-----------username
-----------password
----djgsvnv
-----------email
-----------username
-----------password
You're calling setAdapter() before the data is available from your listener. addValueEventListener is asynchronous and returns immediately, which means you're passing an empty list to the adapter. Put log messages throughout your code to see the order in which it's executing.
Instead, you could call setAdapter in the callback after all the data from the snapshot is available.

Reading data from Firebase database

I want to apply a join operation on 2 nodes in firebase database. How will I do this?
Following is the structure of my database :
I have two nodes : user node and books node
I want to traverse books node and For every book I need to find every user's name (available in user node) who like that book .
I need to make an array of such names and display it in recycler view.
Is there any function which will trigger when all the data will be fetched?
Here is my code:
DatabaseReference bookRef;
bookRef.addOnSingleValueEventListener(new ValueEventListener ){
#Override
public void OnDataChanged(DataSnapshot datasnapshot){
//I will get userReference fromdatasnapshot
DatabaseReference userReference ;
userReference.addOnSingleValueEventListener(new ValueEventListener ){
#Override
public void OnDataChanged(DataSnapshot datasnapshot){
//Add Username in arrayList
}
}
}
}
You can add a HashMap<> for storing the likes of user which like the book inside the book node then you will have no need to travrse through the user node you can get the value of like Hashmap and set as recycle view or what you want

FireBase Android Need 1 value saved under a single user

I have the following data structure on firebase for the user MF0qeRA4p7djfjgXxqwFOck3m6p02. I want to get the value of item3 to populate a single field into the User interface on an Android App. I have been looking through samples on Stackoverflow, but all I have found are outdated and do not work with the current version of firebase. I'm new to firebase completely and this is my first app on android. I've got the oncreate user method to populate the users email address and add the 4 item fields, but retrieving the data I'm completely lost and I am not sure where to even begin.
-Users
---MF0qeRA4p7djfjgXxqwFOck3m6p02
------item1:"1"
------item2:"2"
------item3:"3"
------item4:"4"
According to what I can identify is, you are facing problem retrieving data from this reference. Here is the code:
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users");
databaseReference.child("MF0qeRA4p7djfjgXxqwFOck3m6p02").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> map=(Map<String, Object>)dataSnapshot.getValue();
String item3=(String)map.get("item3");
display(item3);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope this helps.
You can create a custom model and inside you can insert elements. Something like this:
public class Item {
private List<Object> ojects;
}
There you can save instance of Item on database. In this case you have more controll. Other case is to use push() method, that will generate a new encoded key, something like this:
mDatabase.child("items").push().put(new Object());

Android Contacts List View same like Whatsapp using Firebase database

What approach is Whatsapp using to show an "Invite" button for contacts which are not on Whatsapp?
I also want to show a button in Contact list view for only those which don't exist in my app in Firebase database.
I am using Custom BaseAdapter to show contacts in List View.
Can you please help me in understanding how Whatsapp Contact is working?
My Question is not duplicate as that is to read contact list only. I want to show 'Invite' button also as per firebase data.
Thanks!
Well I am not confident what exactly whatsapp is using but as I can the contacts that are not on whatsapp appear in the last. So you can dump the contact list from your firebase Db then query the contacts in the device and make two arraylist in which one is having contact list present in your app means your app users then another is the new users then merge them and show in the Recyclerview or Listview as per your requirement and for invite button you can use different cell layout which contais a button by setting any bool in array list and check it in your base adapter or you can also set its visibility in the same cell as per data in your arraylist.
First of All you have to get the all contacts from clients device,
Note : You Have to Check For Contacts Permissions by your self & don't Forgot to add Permissions Manifest.
Call initData() in onCreate or After Checking Permissions.
here is the code to get Contacts from Clients Device.
private void initData() {
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,null);
while(Objects.requireNonNull(cursor).moveToNext()){
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// Finds the contact in our database through the Firebase Query to know whether that contact is using our app or not.
findUsers(number);
}
}
While Getting Each Contact one by one from clients device, simultaneously we will trigger the firebase query to check whether that contact is using our app or not.
So we are using "findUser" Method to check whether that contact is using our app or not.
private void findUsers(final String number){
Query query = FirebaseDatabase.getInstance().getReference()
.child("User")
.orderByChild("phone")
.equalTo(number);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.getValue() != null){
Map<String, Object> map = (Map<String, Object>) snapshot.getValue();
// this will print whole map of contacts who is using our app from clients contacts.
Log.d("ContactSync", snapshot.getValue().toString());
// so you can use any value from map to add it in your Recycler View.
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("ContactSync", error.getMessage());
}
});
}
Here is how my database structure looks like.
Thanks for reading this answer,
I hope this will be helpful!

Categories

Resources