Android Firebase Listview ---> Hashmap Fail - android

I am trying to retrieve the Restaurant Name data from Firebase and output them in individual lines on ListView. I created a sample of the data which only consists of numbers(strings).
Retrieving the data seems fine as I could output them line by line in console, but my Hashmap is saving everything into the same "node" or "field"
Can anyone help me understand what I did wrong?
#Override
public void onDataChange(DataSnapshot Snapshot) {
int x = 1;
//Do some stuff once
for (DataSnapshot RestNames : Snapshot.getChildren()) {
name = RestNames.getValue().toString();
//System.out.println(name);
map.put(x, name);
x=x+1;
}
System.out.println(map);
Items.add(map);
System.out.println(Items);
listView.setAdapter(mgadapter);
}
The Output in the console is as follows :
{8=3456, 11=9, 9=34567, 5=3, 3=3, 4=4, 10=0, 1=1, 7=345, 6=34, 2=2}
Android emulator shows the same value for every single row.
I want to display each value on a separate row.
Thank you!
EDIT: SNIPPET OF JSON
{
"Eat": {
"Name": {
"-Jy3yehAkgqhg4knlxx_": "1",
"-Jy3yjQT2AxtZMqD2kov": "2",
"-Jy3yk96Mo5MKOEEzviJ": "3",
"-Jy3yksamL08R0BckxNZ": "4",
"-Jy5JBJYZUTxZQtmdDmi": "3",
"-Jy5JIXT_lDZrUOkF3T1": "34",
"-Jy5JJ0oMqGrs2vfFge2": "345",
"-Jy5JJTyET830PYOT3yA": "3456",
"-Jy5JJu-jDGMDXncWDKf": "34567",
"-Jy5JVejdsUtggM8vBoi": "0",
"-Jy5JbwEoWrKAi6XIVQY": "9"
}
}
}

Since we're missing some code in your snippet, I completed it an ran it locally:
Firebase ref = new Firebase("https://stackoverflow.firebaseio.com/32367022/Eat/Name");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
int x = 1;
Map<Integer,Object> map = new HashMap<Integer, Object>();
for (DataSnapshot child: snapshot.getChildren()) {
String name = child.getValue().toString();
System.out.println(name);
map.put(x, name);
x=x+1;
}
System.out.println(map);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
This prints out the following for me:
1
2
3
4
3
34
345
3456
34567
0
9
{1=1, 2=2, 3=3, 4=4, 5=3, 6=34, 7=345, 8=3456, 9=34567, 10=0, 11=9}
The first lines show the output from inside the for loop. The last lines shows the HashMap.
I use the most basic of Java classes, and this behavior seems correct to me.
I expect that the System.out.println(name); inside the for loop will display the same output as above for you, because the Firebase SDK handles ordering there.
If the order in the loop is correct, either your map or your Items object changes the order. It is impossible to say without seeing the types of these.
But in general, the approach above is how you should troubleshoot this problem: isolate it to a single object/class and then either fix what's wrong with that class (if it's your code) or replace it with a class that works for your use-case (if it comes from a library).
Update: I created a minimal app that shows the numbers in the correct order in a list view in this Github repo.

Related

How do I retrieve all child data from a specific node in Firebase on Android?

I have a firebase database that is loaded via Async, and I can verify that all data exists in the correct nodes, but for some reason I can't figure out how to call for the data stored in the particular node.
I've tried .addChildEventListener and .addValueEventListener, but nothing seems to allow for my global object to be loaded with the details at the particular node.
Here's a quick snapshot of json looks like for each node.
{
"movies" : {
"297802" : {
"movieBackdrop" : "/5A2bMlLfJrAfX9bqAibOL2gCruF.jpg",
"movieFavorite" : 0,
"movieID" : 297802,
"movieLanguage" : "en",
"movieOverview" : "Once home to the most advanced civilization on Earth, the city of Atlantis is now an underwater kingdom ruled by the power-hungry King Orm. With a vast army at his disposal, Orm plans to conquer the remaining oceanic people -- and then the surface world. Standing in his way is Aquaman, Orm's half-human, half-Atlantean brother and true heir to the throne. With help from royal counselor Vulko, Aquaman must retrieve the legendary Trident of Atlan and embrace his destiny as protector of the deep.",
"moviePopularity" : 116,
"moviePosterPath" : "/5Kg76ldv7VxeX9YlcQXiowHgdX6.jpg",
"movieReleaseDate" : "2018-12-07",
"movieTitle" : "Aquaman",
"movieVoteAverage" : 6.8,
"movieVoteCount" : 3668
},
"299536" : {
"movieBackdrop" : "/bOGkgRGdhrBYJSLpXaxhXVstddV.jpg",
"movieFavorite" : 0,
"movieID" : 299536,
"movieLanguage" : "en",
"movieOverview" : "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.",
"moviePopularity" : 109,
"moviePosterPath" : "/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
"movieReleaseDate" : "2018-04-25",
"movieTitle" : "Avengers: Infinity War",
"movieVoteAverage" : 8.3,
"movieVoteCount" : 11448
},
I've created my Firebase Database with the movieID being the key value, rather than the generated values, since my ids will always be unique.
Now when I try to get the snapshot stored as my object via the below method, I keep getting a null error pointing to my object currentMovie when I try to extrapolate some of the objects data to update the UI. I know that when I am checking for .equalTo(String.valueOf(movieID) - it is passing a value that correlates to a valid value that should match up correctly, but I keep getting the null error.
mFirebaseDatabase = FirebaseDatabase.getInstance();
mMovieDatabaseReference = mFirebaseDatabase.getReference().child("movies");
Query movieQuery = mMovieDatabaseReference.orderByChild("movieID").equalTo(String.valueOf(movieID));
movieQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
currentMovie = dataSnapshot.getValue(Movie.class);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Any thoughts or ideas on why I'm having so much difficulty here?
You're comparing strings and integers.
In your JSON it shows that movieID is a numeric value:
"movieID" : 297802
In the code you do:
mMovieDatabaseReference.orderByChild("movieID").equalTo(String.valueOf(movieID))
So that means you're comparing integers and strings, which always returns false. The solution is to compare numbers with numbers:
mMovieDatabaseReference.orderByChild("movieID").equalTo(movieID)

Saving JSON Array List Values to variables

I'm already able to get the JSON ArrayList and display the data using RecyclerView.
Here's how I display the JSON array using RecyclerView :
public void onResponse(Call<List<Fame>> call, Response<List<Fame>> response) {
List<Fame> fame = response.body();
mFameList.addAll(fame);
adapter.notifyDatasetChanged();
progressDialog.dismiss();
rv.setVisibility(View.VISIBLE);
title_text.setVisibility(View.VISIBLE);
}
However, for one activity, I only need to get the values and store them to variables. I'm thinking of looping through the list but not really sure if what I'm doing is right. After storing the values to variables, I'll be able to display images based on the values. Any help is much appreciated.
Here's what I've tried so far, but it's giving me a nullpointer exception error. It works if the JSON array contains only 1 result/item.
progressDialog.dismiss();
List<Profile> p = response.body();
if(p!=null && p.size()>0){
pid = p.get(0).getPid();
fname =p.get(0).getFname();
lname = p.get(0).getLname();
}
Here's a sample of the JSON:
[
{
"Pid": "testID",
"Fname": "testfname1",
"Lname": "testlname1",
},
{
"Pid": "testID",
"Fname": "testfname2",
"Lname": "testlname2",
}
]
So here's how I managed to solve the problem:
List<Fame> fame = response.body();
for(Fame f: fame ){
if(f.getfName.toString() == "testfname1"){
//do something if condition is met
}
//repeat step for others
}
I'm not sure if it's the best way to do it but it satisfies my requirements for now. :)

How to query firebase data in android?

My firebase data looks like these:
"worldwide" : [{
"key1" : {
"movie_id": 100,
"release_date": 1524182400000,
"description": "Cool movie here"
},
"key2" : {
"movie_id": 101,
"release_date": 1525046400000,
"description": "Plot is cool"
}
}]
"europe" : [{
"key1" : {
"movie_id": 100,
"release_date": 1516798528489,
"description": "Cool movie here"
},
"key3" : {
"movie_id": 102,
"release_date": 1525046400000,
"description": "Cool plot"
}
}]
Note: Both lists are inside a man list called releases
I've been trying for the past hours to query my data in java/android so that both data in both list join together to make one complete list with the movies ordered by release_date (which are in milliseconds) and for the duplicate entries I want the release_date information in the Europe array to take priority, so if the movie_id is in both list and it has a different release date in the worldwide array and the Europe array, I want the entry in the Europe array to be saved in in the complete list. For example, "movie_id": 100 appears in both list. Thank you.
My java code:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = null; // I don't know how to structure my query
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot movie: dataSnapshot.getChildren()) {
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Any tips would be appreciated, like I'd like to hear if there's any better method to accomplish what I want.
First and foremost, you need to make sure that your database has the correct .indexOn rules. This will ensure that you can query/sort your data.
Next, you can add the Query to the database reference:
firebase::database::Query query =
reference.GetReference("worldwide").OrderByChild("release_date");
Finally, Read up on the Sorting/Query from the documentation.
To merge the two lists, just run two queries and add the movies into a concurrent list. Then sort the list.
There is no construct in Firebase to read data from both lists with one query. This means that you will have to:
either use two listeners (one on worldwide and one on europe) and merge the results from those listeners in the client.
or use a single listener at the node above worldwide and europe and then iterate over the resulting snapshot.
The latter is simpler in code, but might be less efficient.
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot movie: dataSnapshot.getChild("europe").getChildren()) {
System.out.println(movie.getKey()+": "+movie.getChild("movie_id").getValue());
}
for (DataSnapshot movie: dataSnapshot.getChild("worldwide").getChildren()) {
System.out.println(movie.getKey()+": "+movie.getChild("movie_id").getValue());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw new databaseError.toException();
}
});

Firebase Realtime Database Filter Data in Nested List

I wanted to retrieve filtered data from db according to extra_Cat value like 31
I am able to retrieve full data easily but unable to put filter in it
Note: I have checked almost every solution, If duplicate please reply then tag duplicate
my code is
DBConnection dbConnection=new DBConnection();
postRef=dbConnection.database.getReference("Data");
postRef.child("extra_Cat").orderByKey().equalTo("*31*").limitToLast(500).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long as= dataSnapshot.getChildrenCount();
Log.d("Data", String.valueOf(as));
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
}
});
and JSON is
"32161" : {
"author_name" : "Talented+Desk",
"cat_ID" : "%2A7%2A",
"cat_name" : "%E0%A4%96%E0%A5%87%E0%A4%B2",
"content" : "A4%B5A4%A8%E0%A4%BF%E0%A4%AF%E0%A4%AE+%E0%A4%B9%E0%A5%88%E0%A4%82%7C%E2%80%9D%3C%2Fp%3E%0A",
"extraCat" : [ "*31*", "*14*" ],
"fea_image" : "https%3A%2F%2Fwww.talentedindia.co.in%2Fwp-content%2Fuploads%2F2018%2F03%2Faajeevan-pratibandh-Steve-Smith.jpg",
"post_comment" : "0%A4%BF%E0%A4%AF%E0%A5%8B%E",
"post_date" : "2018-03-26",
"post_id" : "32161",
"post_slug_name" : "kangaroos-protest-against-less-punishment",
"post_status" : "publish",
"post_time" : "10%3A45%3A40",
"post_video" : "",
"slider_image1" : "",
"slider_image2" : "",
"slider_image3" : "",
"slider_image4" : "",
"title" : "%E0%A4%94%B8%E0%A4%9C%E0%A4%BE+%E0%A4%AA%E0%A4%B0+%E0%A4%B5%E0%A4%BF%E0%A4%B0%E0%A5%8B%E0%A4%A7"
},
You cannot create a query based on values that exist within an array. As I see in your database, extraCat is an array which contains 2 values, *31* and *14*.
In order to solve this, you need to change your database structure a little bit. So your extraCat node should look like this:
extraCat
|
--- "*31*": true
|
--- "*14*": true
As you can see, the extraCat node the is now a Map. The corresponding query should look like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Data")
.orderByChild("extra_Cat/*31*")
.equalsTo(true)
.limitToLast(500)
.addValueEventListener(/* ... */)
First you are using wrong reference path. The current you are using is Data/extra_cat. As I see in your Firebase structure it should be Data/32343/extraCat.
You can't use .child("extra_Cat").orderByKey().equalTo("*31*") because the *31* is not of the extra_Cat keys value. The value is in the list.

Realtime database get name and value

i am using firebase real-time database.
there is the user name like - user1 and then some supplies he requested like the supplies name - markers and then the quantity - like 5.
this is my JSON file
{
"Users" : {
"User1" : {
"Markers" : 5,
"Scissors" : 1,
"Staplers" : 4
},
"User2" : {
"Markers" : 2,
"Scissors" : 5,
"Staplers" : 3
}
}
}
i want to get back the supplies whan i ask for in the format of:
markers 5
scissors 1
Staplers 4
the information comes out via a listview but i don't know how to get via the listview both name and quantity, i can get only one of them.
The code i am using to get only the names is:
Set<String> set = new HashSet<String>();
Iterator i = dataSnapshot.getChildren().iterator();
while (i.hasNext()) {
set.add(((DataSnapshot) i.next()).getKey());
}
and the code i am using to get only the quantity is:
// two first lines are the same
while (i.hasNext()) {
set.add(((DataSnapshot) i.next()).getValue().toString());
}
Try something like this instead:
for (DataSnapshot supply : dataSnapshot.getChildren()) {
String key = supply.getKey();
String value = supply.getValue();
}
Also, you could have just saved i.next() to a variable, then you can access the key and value within the same loop without calling additional i.next() (which I presume is what the question is about).
i have changed the script to this one
key = (((DataSnapshot) i.next()).getKey());
value = ((dataSnapshot).child(key).getValue().toString());
set.add(key+" "+value);
it works very good, thanks any way.

Categories

Resources