Failing to Read Nested Data From Firebase Database - android

I am sending "Appetizers and Snacks" which is in name key from one activity 1 to activity 2.
In activity 2,the data received is simply :
intent = getIntent();
String received_id = intent.getStringExtra("cat_id");
Log.e("ID received is", received_id);
Output is :
ID received is : Appetizers and Snacks
With the Help of this value, I'm trying to read the Node recipes and display all the data in their Respective Views.
I only want to know , how can I get to the recipes node. I tried this till now :
query = FirebaseDatabase.getInstance().getReference("All Categories").orderByChild("name").equalTo(received_id);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Log.e("data", String.valueOf(dataSnapshot));
if (dataSnapshot.exists()) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.child("recipes").getChildren()) {
Log.e("data final is ", String.valueOf(dataSnapshot1.getValue()));
DetailModel p = dataSnapshot1.getValue(DetailModel.class);
detailModelList.add(p);
}
detailAdapter = new DetailAdapter(DetailCategory.this, detailModelList);
recyclerView.setAdapter(detailAdapter);
progressBar.setVisibility(View.INVISIBLE);
} else {
Toast.makeText(DetailCategory.this, "No data available !", Toast.LENGTH_SHORT).show();
Log.e("No data available !", "No data available !");
progressBar.setVisibility(View.INVISIBLE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(DetailCategory.this, databaseError.getDetails(), Toast.LENGTH_SHORT).show();
}
});
recyclerView.setLayoutManager(new GridLayoutManager(DetailCategory.this, 2));
The Log.e("data", String.valueOf(datasnapshot)) gives this Output :
DataSnapshot { key = All Categories, value = {0={image=https://i.imgur.com/0toOJMa.jpg, recipes={randomkey={image=https://i.ibb.co/gvH8Vp2/5f6fg0l8-keraal-roast-chicken-62.png, servings=4 servings, ingredients="complete Ingredients here"}}, name=Appetizers and Snacks}} }
My DetailModel class is a simple class :
public DetailModel() {
}
String image,title, time,servings,ingredients,steps;
public DetailModel(Integer id, String image, String title, String time, String servings, String ingredients, String steps) {
this.id = id;
this.image = image;
this.title = title;
this.time = time;
this.servings = servings;
this.ingredients = ingredients;
this.steps = steps;
}
public Integer getId() {
return id;
}
public String getImage() {
return image;
}
public String getTitle() {
return title;
}
public String getTime() {
return time;
}
public String getServings() {
return servings;
}
public String getIngredients() {
return ingredients;
}
public String getSteps() {
return steps;
}
But every time there is no data Received in the App, Completely Blank, even the Else conditions are not executing.
it doesn't reach if (dataSnapshot.exists()) { and none of the code inside is executed. Since, I also checked with settings logs , nothing is found in Logcat as well . Any Tips , why this is happening ?
EDIT : i did as Frank Recommended, Still there is no data in the App
Please Guide me reading this nested Data.

Instead of this:
databaseReference = FirebaseDatabase.getInstance().getReference("All Categories").child("name").orderByValue().equalTo(received_id).getRef();
You'll want to use:
Query query = FirebaseDatabase.getInstance().getReference("All Categories").orderByChild("name").equalTo(received_id);
So:
Use orderByChild("name") to tell the database to order all child nodes on the value of their name property.
Use equalTo(...) to then filter down the sorted data.
Remove the getRef() as that actually undoes all your query buildin.
To then read the data, do:
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot categorySnapshot: dataSnapshot.getChildren()) {
for (DataSnapshot recipeSnapshot: categorySnapshot.child("recipes").getChildren()) {
DetailModel p = recipeSnapshot.getValue(DetailModel.class);
detailModelList.add(p);
}
}
detailAdapter = new DetailAdapter(DetailCategory.this, detailModelList);
recyclerView.setAdapter(detailAdapter);
progressBar.setVisibility(View.INVISIBLE);
} else {
Toast.makeText(DetailCategory.this, "No data available !", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.INVISIBLE);
}
}
So:
Listen to the entire query we just created.
Then loop over the children of recipes of each node we get back in the snapshot.

databaseReference = FirebaseDatabase.getInstance().getReference();
val ref = database.child("All Categories").child("0").child("recipes")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val recipes = dataSnapshot.getValue(Recipes::class.java) // recipes model reading
}
override fun onCancelled(databaseError: DatabaseError) {
}
}
ref.addListenerForSingleValueEvent(valueEventListener)

Related

Attempt to invoke virtual method on a null object reference .child() Firebase database

Here is how I intend my code to work. I first make sure that a unique placeID VALUE exists in my database (as seen in the picture), and set it to the query object. If the dataSnapshot of that VALUE exists, I want to retrieve the corresponding businessID using
businessID = resInfo_P.getBusinessID();
However it returns a null object reference.
Question: How do I retrieve the businessID VALUE without returning a null?
Code:
ref2 = FirebaseDatabase.getInstance().getReference();
mDatabase = FirebaseDatabase.getInstance().getReference();
Query query = ref2.child("place_id").orderByChild("placeID").equalTo(resID);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
RestaurantInformation resInfo_P = dataSnapshot
.child("place_id")
.child(resID).getValue(RestaurantInformation.class);
businessID = resInfo_P.getBusinessID(); // null object exception
} else {
...
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Model
public class RestaurantInformation {
private String resName;
private String status;
private String businessID;
private String placeID;
public RestaurantInformation() {
}
public RestaurantInformation(String businessID, String placeID) {
this.businessID = businessID;
this.placeID = placeID;
}
public RestaurantInformation(String resName) {
this.resName = resName;
}
public String getResName() {
return resName;
}
public void setResName(String resName) {
this.resName = resName;
}
public String getBusinessID() {
return businessID;
}
public void setBusinessID(String placeID) {
this.businessID = placeID;
}
public String getPlaceID() {
return placeID;
}
public void setPlaceID(String placeID) {
this.placeID = placeID;
}
}
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
You will need to handle this list in your code by iterating over the children of the snapshot:
Query query = ref2.child("place_id").orderByChild("placeID").equalTo(resID);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
RestaurantInformation resInfo_P = childSnapshot.getValue(RestaurantInformation.class);
businessID = resInfo_P.getBusinessID();
}
} else {
...
}

How to retrieve user details by user id inside for loop?

I have structured my firebase database like this:
And this is the way how i would structure my tables in database with SQL if i want to fetch user details by passing id as parameter.
But this is not working as i expected.
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
for (final DataSnapshot snapshot : dataSnapshot.getChildren()) {
final String taskName = snapshot.child("name").getValue(String.class);
final String assignedUserId = snapshot.child("assignedUserId").getValue(String.class);
final String categoryId = snapshot.child("categoryId").getValue(String.class);
final Boolean completed = snapshot.child("completed").getValue(Boolean.class);
final String priority = snapshot.child("priority").getValue(String.class);
User user = getUser(assignedUserId);
ProjectTask projectTask
= new ProjectTask(snapshot.getKey(), dataSnapshot.getKey(), taskName, assignedUserId, priority, completed, categoryId, user);
mProjectTaskList.add(projectTask);
}
for (Category category : mCategories) {
mProjectTasksSection = getTasksWithSection(category);
if (mProjectTasksSection.size() > 0) {
mSectionedRecyclerViewAdapter.addSection(new ProjectTaskListAdapter(R.layout.lst_todo_item_v2, mProjectTasksSection,
category, getActivity()));
}
}
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerProjectTasks.setLayoutManager(linearLayoutManager);
recyclerProjectTasks.setItemAnimator(new DefaultItemAnimator());
recyclerProjectTasks.setAdapter(mSectionedRecyclerViewAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here i have fetched all tasks and now i just need one more parameter and that is user details, but i really don't know how to get it. I'm not really sure if this is the right way. Maybe it would be easier if i store user name instead of user id. Below i will post my code trying to fetch user details by id:
private User getUser(String keyId) {
DatabaseReference databaseReference = AppController.getInstance().getDatabase()
.getReference().child("users").child(keyId);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return null;
}
for(DataSnapshot postSnapshot:dataSnapshot.getChildren())
{
//pass name here that you want to
// if(postSnapshot.getKey().equals("name".equalsIgnoreCase(nameStr)))
//compare
if(postSnapshot.getKey().equals("name"))
{
final String taskName = snapshot.child("name").getValue(String.class);
//taskName =postSnapshot.getValue().toString();
}
}
Please see this post.
Your DatabaseReference is correct but you don't need to use getChildren() method on the 'dataSnapshot`. Just remove the second iteration. You code should look like this:
public void onDataChange(final DataSnapshot dataSnapshot) {
final String taskName = snapshot.child("name").getValue(String.class);
final String assignedUserId = snapshot.child("assignedUserId").getValue(String.class);
final String categoryId = snapshot.child("categoryId").getValue(String.class);
final Boolean completed = snapshot.child("completed").getValue(Boolean.class);
final String priority = snapshot.child("priority").getValue(String.class);
User user = getUser(assignedUserId);
ProjectTask projectTask = new ProjectTask(snapshot.getKey(), dataSnapshot.getKey(), taskName, assignedUserId, priority, completed, categoryId, user);
mProjectTaskList.add(projectTask);
}
Hope it helps.

Retrieve a List of Objects from another object stored in Firebase Database

I've searched a lot of posts in order to find a solution, but i couldn't find one.
I have 2 classes a Recipe class:
public class Recepta {
private String nom;
private List<Ingredient> ingredients;
private List<String> pasos;
public Recepta() {
}
public Recepta(String nom,List<Ingredient> ingredients, List<String> pasos) {
this.nom = nom;
this.ingredients = ingredients;
this.pasos = pasos;
}
//Getter and setters
}
and my Ingredient class:
public class Ingredient {
private String nom;
private String quantitat;
public Ingredient(){
}
public Ingredient(String nom,String quantitat){
this.nom = nom;
this.quantitat = quantitat;
}
//Getter and setters
}
And my DB's structure :
3ER2U0QSDTMHRdKA0eO231UCQeY2
8eJaHRU9f5ZrVogqhx0Hj1iFcgG2
-jdhd
-ingredients
-0
-nom: "bdhd"
-quantitat: "b,bzh"
-nom:"jdhd"
-pasos
-0: "djdjjd"
-jdjd
-jdjdvshs
AfcGeBzvdLRq19J3kRk3CVg30np2
fk39ClAVaQNFQCONU9Agp0KfUUf1addclose
As you can see, "pasos" is a List of String and "ingredients" is a List of Ingredient.
What I can't find out is how can I retrieve those lists from database as I want to get a List of Recepta.
I've tried a lot of things but all were wrong as it didn't retrieve any of the lists.
That's what I've tried, but i know that doesn't work because Firebase DB doesn't store lists as a List
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final DatabaseReference listReference = FirebaseDatabase.getInstance().getReference(user.getUid());
listReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(final DataSnapshot listSnapshot: dataSnapshot.getChildren()){
receptas.add(listSnapshot.getValue(Recepta.class));
}
listReceptaAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I also know that FB DB work with HashMaps but i dont know how to retrieve them or pass from a hashmap to a list without having to go through every position of hashmap
So what should I do? Thank you in advance
I think the below example would help to integrate two data in one list in firebase database
public static ArrayList<MuteModel> muteModelList;
public void updateMuteListServer(){
DatabaseReference frndMuteRef = FirebaseDatabase.getInstance().getReference().child("users/" + getFirebaseUser().getUid().trim() + "/friendlists");
Query queryRef = frndMuteRef.orderByChild(MUTE).equalTo(YES);
queryRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
GenericTypeIndicator<HashMap<String,MuteModel>> t= new GenericTypeIndicator<HashMap<String,MuteModel>>() { };
HashMap<String,MuteModel> hashMap= (HashMap<String,MuteModel>)dataSnapshot.getValue(t);
if(hashMap!=null) {
muteModelList = new ArrayList<MuteModel>(hashMap.values());
for (MuteModel muteModel: muteModelList){
muteModel.setIsgroup(NO);
}
}else{
muteModelList = new ArrayList<MuteModel>();
}
findGroupMuteList();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void findGroupMuteList() {
DatabaseReference groupMuteRef = FirebaseDatabase.getInstance().getReference().child("users/" + getFirebaseUser().getUid().trim() + "/"+GROUPS);
Query queryRef = groupMuteRef.orderByChild(MUTE).equalTo(YES);
queryRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
GenericTypeIndicator<HashMap<String,MuteModel>> t= new GenericTypeIndicator<HashMap<String,MuteModel>>() { };
HashMap<String,MuteModel> hashMap= (HashMap<String,MuteModel>)dataSnapshot.getValue(t);
ArrayList<MuteModel> properties;
if(hashMap!=null) {
properties = new ArrayList<MuteModel>(hashMap.values());
for (MuteModel muteModel:properties){
muteModel.setIsgroup(YES);
}
}else{
properties = new ArrayList<MuteModel>();
}
MyChat.muteModelList.addAll(properties);
Gson gson = new Gson();
String strMuteList = gson.toJson(MyChat.muteModelList);
editSharedPref(MUTELIST,strMuteList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
in your case I think the generic adapter of ingredients will look like as follows
GenericTypeIndicator<ArrayList<Ingredients>>
& in case of pasos you can do like
GenericTypeIndicator<ArrayList<Strings>>

Cannot read list from Firebase, Map expected [duplicate]

I want to convert all Firebase DataSnapshot children to a list in android.
Something like this:
mFirebaseRef = new Firebase(FIREBASE_URL);
mFirebaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> td = (ArrayList<String>) dataSnapshot.getValue();
//notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
I hope below code works
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.e("Count " ,""+snapshot.getChildrenCount());
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
<YourClass> post = postSnapshot.getValue(<YourClass>.class);
Log.e("Get Data", post.<YourMethod>());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("The read failed: " ,firebaseError.getMessage());
}
});
Firebase stores a sequence of values in this format:
"-K-Y_Rhyxy9kfzIWw7Jq": "Value 1"
"-K-Y_RqDV_zbNLPJYnOA": "Value 2"
"-K-Y_SBoKvx6gAabUPDK": "Value 3"
If that is how you have them, you are getting the wrong type. The above structure is represented as a Map, not as a List:
mFirebaseRef = new Firebase(FIREBASE_URL);
mFirebaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();
List<Object> values = td.values();
//notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = mFirebaseDatabase.getReference(FIREBASE_URL);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
Log.v(TAG,""+ childDataSnapshot.getKey()); //displays the key for the node
Log.v(TAG,""+ childDataSnapshot.child(--ENTER THE KEY NAME eg. firstname or email etc.--).getValue()); //gives the value for given keyname
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope it helps!
as Frank said Firebase stores sequence of values in the format of "key": "Value"
which is a Map structure
to get List from this sequence you have to
initialize GenericTypeIndicator with HashMap of String and your Object.
get value of DataSnapShot as GenericTypeIndicator into Map.
initialize ArrayList with HashMap values.
GenericTypeIndicator<HashMap<String, Object>> objectsGTypeInd = new GenericTypeIndicator<HashMap<String, Object>>() {};
Map<String, Object> objectHashMap = dataSnapShot.getValue(objectsGTypeInd);
ArrayList<Object> objectArrayList = new ArrayList<Object>(objectHashMap.values());
Works fine for me, Hope it helps.
I did something like this :
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Map<String, Object> objectMap = (HashMap<String, Object>)
dataSnapshot.getValue();
List<Match> = new ArrayList<Match>();
for (Object obj : objectMap.values()) {
if (obj instanceof Map) {
Map<String, Object> mapObj = (Map<String, Object>) obj;
Match match = new Match();
match.setSport((String) mapObj.get(Constants.SPORT));
match.setPlayingWith((String) mapObj.get(Constants.PLAYER));
list.add(match);
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
In my case only given solution worked fine.
Screenshot of Firebase ArrayList structure:
How to fetch whole list from Firebase from DataSnapshot.
GenericTypeIndicator<Map<String, List<Education>>> genericTypeIndicator = new GenericTypeIndicator<Map<String, List<Education>>>() {};
Map<String, List<Education>> hashMap = dataSnapshot.getValue(genericTypeIndicator);
for (Map.Entry<String,List<Education>> entry : hashMap.entrySet()) {
List<Education> educations = entry.getValue();
for (Education education: educations){
Log.i(TAG, education.Degree);
}
}
Education.java: (Model class).
public class Education implements Serializable{
public String Degree;
public String Result;
}
Hope this would works fine.
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
User user = postSnapshot.getValue(User.class);
list.add(user);
}
for (int i=0;i<list.size();i++)
{
Log.e("Name",list.get(i).getname());
Log.e("Phone",list.get(i).getphone());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("error",firebaseError.getMessage());
}
});
Class model
class User{
String name;
String phone;
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getphone() {
return phone;
}
public void setphone(String phone) {
this.phone = phone;
}
}
List binding
List<User> list= new ArrayList <>();
this work for you
If you use Kotlin, the next one is a good solution:
myRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val list = dataSnapshot.children.map { it.getValue(YourClass::class.java)!! }
Log.d("TAG", "Value is: $list")
}
Saving and Retriving data to - from Firebase ( deprecated ver 2.4.2 )
Firebase fb_parent = new Firebase("YOUR-FIREBASE-URL/");
Firebase fb_to_read = fb_parent.child("students/names");
Firebase fb_put_child = fb_to_read.push(); // REMEMBER THIS FOR PUSH METHOD
//INSERT DATA TO STUDENT - NAMES I Use Push Method
fb_put_child.setValue("Zacharia"); //OR fb_put_child.setValue(YOUR MODEL)
fb_put_child.setValue("Joseph"); //OR fb_put_child.setValue(YOUR MODEL)
fb_put_child.setValue("bla blaaa"); //OR fb_put_child.setValue(YOUR MODEL)
//GET DATA FROM FIREBASE INTO ARRAYLIST
fb_to_read.addValuesEventListener....{
public void onDataChange(DataSnapshot result){
List<String> lst = new ArrayList<String>(); // Result will be holded Here
for(DataSnapshot dsp : result.getChildren()){
lst.add(String.valueOf(dsp.getKey())); //add result into array list
}
//NOW YOU HAVE ARRAYLIST WHICH HOLD RESULTS
for(String data:lst){
Toast.make(context,data,Toast.LONG_LENGTH).show;
}
}
}
mDatabase.child("token").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot:dataSnapshot.getChildren())
{
String key= snapshot.getKey();
String value=snapshot.getValue().toString();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ListUser.this,databaseError.toString(),Toast.LENGTH_SHORT).show();
}
});
Only work If child have no SubChild
Works Like a Charm
final DatabaseReference senderDb = FirebaseDatabase.getInstance().getReference(Constant.NODE_MESSAGE).child(myId + "_" + otherId);
senderDb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
DatabaseReference objRef = senderDb.child( childDataSnapshot.getKey());
Map<String,Object> taskMap = new HashMap<String,Object>();
taskMap.put("is_read", "1");
objRef.updateChildren(taskMap); //should I use setValue()...?
Log.v("Testing",""+ childDataSnapshot.getKey()); //displays the key for the node
}
//notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You Need to write a custom Deserializer and then loop it and get the values of the hasmap.
Custom Deserializer:-
public class UserDetailsDeserializer implements JsonDeserializer<AllUserDetailsKeyModel> {
/*
bebebejunskjd:{
"email": "akhilbv1#gmail.com",
"mobileNum": "12345678",
"password": "1234567",
"username": "akhil"}*/
#Override public AllUserDetailsKeyModel deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
final JsonObject jsonObject = json.getAsJsonObject();
Gson gson = new Gson();
Type AllUserDetailsResponseModel =
new TypeToken<HashMap<String, AllUserDetailsResponseModel>>(){}.getType();
HashMap<String, AllUserDetailsResponseModel> user =
gson.fromJson(jsonObject, AllUserDetailsResponseModel);
AllUserDetailsKeyModel result = new AllUserDetailsKeyModel();
result.setResult(user);
return result;
}
}
The code in comments is my object model and u should replaceAllUserDetailsKeyModel with your model class and add this to the rest client like below:-
private Converter.Factory createGsonConverter() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(AllUserDetailsKeyModel.class, new UserDetailsDeserializer());
Gson gson = gsonBuilder.create();
return GsonConverterFactory.create(gson);
}
This the custom Convertor for Retrofit.
In your onResponse you just loop with hasmaps and get value by key and my model class looks like below:-
public class AllUserDetailsKeyModel {
private Map<String, AllUserDetailsResponseModel> result;
public Map<String, AllUserDetailsResponseModel> getResult() {
return result;
}
public void setResult(Map<String, AllUserDetailsResponseModel> result) {
this.result = result;
}
}
probably you need to give a Type T where T is your data Type and my model consists only of a hashmap and getters and setters for that.
And finally set Custom Convertor to retrofit like below:- .addConverterFactory(createGsonConverter())
Let me know if you need more clarifications.
Use GenericTypeIndicator to get List of Child Node from Firebase ArrayList structured DataBase
//Start of Code
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot snapshot){
GenericTypeIndicator<List<YourClassName>> t = new GenericTypeIndicator<List<YourClassName>>{};
List<YourClassName> messages = snapshot.getValue(t);
Log.d("Get Data Size", messages.size());
}
}
#Override
public void onCancelled(FirebaseError firebaseError){
Log.e("The read failed: ",firebaseError.getMessage());
}
});
your problem is why your code doesn't work.
this your code:
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.e("Count " ,""+snapshot.getChildrenCount());
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
<YourClass> post = postSnapshot.getValue(<YourClass>.class);
Log.e("Get Data", post.<YourMethod>());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("The read failed: " ,firebaseError.getMessage());
}
})
you miss the simplest thing: getChildren()
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference reference = FirebaseAuth.getInstance().getReference("Donald Trump");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int count = (int) dataSnapshot.getChildrenCount(); // retrieve number of childrens under Donald Trump
String[] hairColors = new String[count];
index = 0;
for (DataSnapshot datas : dataSnapshot.getChildren()){
hairColors[index] = datas.getValue(String.class);
}
index ++
for (int i = 0; i < count; i++)
Toast(MainActivity.this, "hairColors : " + hairColors[i], toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
ArrayList<String> keyList = new ArrayList<String>();
mKeyRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
String temp = childDataSnapshot.getKey();
keyList.add(temp);
i = keyList.size();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
This code is working fine to add all firebase key into arraylist, you can do it with firebase values, of other static values.
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mMainMenuRef = mRootRef.child("tut_master");//main
DatabaseReference mSubMenuRef = mMainMenuRef.child("english");//sub
List<Tutorial> tutorialNames=new ArrayList<>();
mSubMenuRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
long id = ds.child("id").getValue(Long.class);
String name = ds.child("name").getValue(String.class);
Tutorial tut = new Tutorial();
tut.setTutId(id+"");
tut.setTutName(name);
tutList.add(tut);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
private FirebaseDatabase firebaseDatabase= FirebaseDatabase.getInstance();
private DatabaseReference databaseReference= firebaseDatabase.getReference();
private DatabaseReference mChildReference= databaseReference.child("data");
mChildReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
User commandObject = ds.getValue(User.class);
Log.d("TAG", commandObject.getMsg());
}
Toast.makeText(MainActivity.this,dataSnapshot.toString(),Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This will help you, you just have to create a model class containing String msg.
Use Gson is my favorite solution.
mFirebaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Type StringListType = new TypeToken<List<String>>(){}.getType();
List<String> td = new Gson().fromJson(dataSnapshot.getValue(), StringListType);
}
});
if you think the code to get TypeToken is unintuitive. You can write a class to contain all types you need. So next time, you can get those types quickly.
class TypeTokens{
static public final Type StringListType = new TypeToken<List<String>>(){}.getType();
static public final Type StringMapType = new TypeToken<Map<String, String>>(){}.getType();
static public final Type LongMapType = new TypeToken<Map<String, Long>>(){}.getType();
static public final Type DateMapType = new TypeToken<Map<String, Date>>(){}.getType();
}
Here goes my 2 cents contribution (in Kotlin):
private fun getData(childUid:String) {
refDB = firebaseDB.reference.child(MAIN_DATABASE_FOLDER).child(childUid)
if(childEventDataListener == null) {
childEventDataListener = object : ChildEventListener {
override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
for(snap in snapshot.children) {
val newParcel = snapshot.getValue(YourClassConverter::class.java)!!
}
}
override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) { }
override fun onChildRemoved(snapshot: DataSnapshot) { }
override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
override fun onCancelled(error: DatabaseError) {}
}
refDB.addChildEventListener(childEventDataListener!!)
}
}
The class YourClassConverter shall follow this rule as noted in the getValue header's comment shown below. I prefer to use this converter since I can control the default values passed when some of them are not defined in the firebase.
This method is used to marshall the data contained in this snapshot into a class of your choosing. The class must fit 2 simple constraints:
The class must have a default constructor that takes no arguments
The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized
An example class might look like:
class Message {
private String author;
private String text;
private Message() {}
public Message(String author, String text) {
this.author = author;
this.text = text;
}
public String getAuthor() {
return author;
}
public String getText() {
return text;
}
}
// Later
Message m = snapshot.getValue(Message.class);

How to extract a list of objects from Firebase DataSnapshot on android

I want to convert all Firebase DataSnapshot children to a list in android.
Something like this:
mFirebaseRef = new Firebase(FIREBASE_URL);
mFirebaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> td = (ArrayList<String>) dataSnapshot.getValue();
//notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
I hope below code works
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.e("Count " ,""+snapshot.getChildrenCount());
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
<YourClass> post = postSnapshot.getValue(<YourClass>.class);
Log.e("Get Data", post.<YourMethod>());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("The read failed: " ,firebaseError.getMessage());
}
});
Firebase stores a sequence of values in this format:
"-K-Y_Rhyxy9kfzIWw7Jq": "Value 1"
"-K-Y_RqDV_zbNLPJYnOA": "Value 2"
"-K-Y_SBoKvx6gAabUPDK": "Value 3"
If that is how you have them, you are getting the wrong type. The above structure is represented as a Map, not as a List:
mFirebaseRef = new Firebase(FIREBASE_URL);
mFirebaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();
List<Object> values = td.values();
//notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = mFirebaseDatabase.getReference(FIREBASE_URL);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
Log.v(TAG,""+ childDataSnapshot.getKey()); //displays the key for the node
Log.v(TAG,""+ childDataSnapshot.child(--ENTER THE KEY NAME eg. firstname or email etc.--).getValue()); //gives the value for given keyname
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope it helps!
as Frank said Firebase stores sequence of values in the format of "key": "Value"
which is a Map structure
to get List from this sequence you have to
initialize GenericTypeIndicator with HashMap of String and your Object.
get value of DataSnapShot as GenericTypeIndicator into Map.
initialize ArrayList with HashMap values.
GenericTypeIndicator<HashMap<String, Object>> objectsGTypeInd = new GenericTypeIndicator<HashMap<String, Object>>() {};
Map<String, Object> objectHashMap = dataSnapShot.getValue(objectsGTypeInd);
ArrayList<Object> objectArrayList = new ArrayList<Object>(objectHashMap.values());
Works fine for me, Hope it helps.
I did something like this :
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Map<String, Object> objectMap = (HashMap<String, Object>)
dataSnapshot.getValue();
List<Match> = new ArrayList<Match>();
for (Object obj : objectMap.values()) {
if (obj instanceof Map) {
Map<String, Object> mapObj = (Map<String, Object>) obj;
Match match = new Match();
match.setSport((String) mapObj.get(Constants.SPORT));
match.setPlayingWith((String) mapObj.get(Constants.PLAYER));
list.add(match);
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
In my case only given solution worked fine.
Screenshot of Firebase ArrayList structure:
How to fetch whole list from Firebase from DataSnapshot.
GenericTypeIndicator<Map<String, List<Education>>> genericTypeIndicator = new GenericTypeIndicator<Map<String, List<Education>>>() {};
Map<String, List<Education>> hashMap = dataSnapshot.getValue(genericTypeIndicator);
for (Map.Entry<String,List<Education>> entry : hashMap.entrySet()) {
List<Education> educations = entry.getValue();
for (Education education: educations){
Log.i(TAG, education.Degree);
}
}
Education.java: (Model class).
public class Education implements Serializable{
public String Degree;
public String Result;
}
Hope this would works fine.
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
User user = postSnapshot.getValue(User.class);
list.add(user);
}
for (int i=0;i<list.size();i++)
{
Log.e("Name",list.get(i).getname());
Log.e("Phone",list.get(i).getphone());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("error",firebaseError.getMessage());
}
});
Class model
class User{
String name;
String phone;
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getphone() {
return phone;
}
public void setphone(String phone) {
this.phone = phone;
}
}
List binding
List<User> list= new ArrayList <>();
this work for you
If you use Kotlin, the next one is a good solution:
myRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val list = dataSnapshot.children.map { it.getValue(YourClass::class.java)!! }
Log.d("TAG", "Value is: $list")
}
Saving and Retriving data to - from Firebase ( deprecated ver 2.4.2 )
Firebase fb_parent = new Firebase("YOUR-FIREBASE-URL/");
Firebase fb_to_read = fb_parent.child("students/names");
Firebase fb_put_child = fb_to_read.push(); // REMEMBER THIS FOR PUSH METHOD
//INSERT DATA TO STUDENT - NAMES I Use Push Method
fb_put_child.setValue("Zacharia"); //OR fb_put_child.setValue(YOUR MODEL)
fb_put_child.setValue("Joseph"); //OR fb_put_child.setValue(YOUR MODEL)
fb_put_child.setValue("bla blaaa"); //OR fb_put_child.setValue(YOUR MODEL)
//GET DATA FROM FIREBASE INTO ARRAYLIST
fb_to_read.addValuesEventListener....{
public void onDataChange(DataSnapshot result){
List<String> lst = new ArrayList<String>(); // Result will be holded Here
for(DataSnapshot dsp : result.getChildren()){
lst.add(String.valueOf(dsp.getKey())); //add result into array list
}
//NOW YOU HAVE ARRAYLIST WHICH HOLD RESULTS
for(String data:lst){
Toast.make(context,data,Toast.LONG_LENGTH).show;
}
}
}
mDatabase.child("token").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot:dataSnapshot.getChildren())
{
String key= snapshot.getKey();
String value=snapshot.getValue().toString();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ListUser.this,databaseError.toString(),Toast.LENGTH_SHORT).show();
}
});
Only work If child have no SubChild
Works Like a Charm
final DatabaseReference senderDb = FirebaseDatabase.getInstance().getReference(Constant.NODE_MESSAGE).child(myId + "_" + otherId);
senderDb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
DatabaseReference objRef = senderDb.child( childDataSnapshot.getKey());
Map<String,Object> taskMap = new HashMap<String,Object>();
taskMap.put("is_read", "1");
objRef.updateChildren(taskMap); //should I use setValue()...?
Log.v("Testing",""+ childDataSnapshot.getKey()); //displays the key for the node
}
//notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You Need to write a custom Deserializer and then loop it and get the values of the hasmap.
Custom Deserializer:-
public class UserDetailsDeserializer implements JsonDeserializer<AllUserDetailsKeyModel> {
/*
bebebejunskjd:{
"email": "akhilbv1#gmail.com",
"mobileNum": "12345678",
"password": "1234567",
"username": "akhil"}*/
#Override public AllUserDetailsKeyModel deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
final JsonObject jsonObject = json.getAsJsonObject();
Gson gson = new Gson();
Type AllUserDetailsResponseModel =
new TypeToken<HashMap<String, AllUserDetailsResponseModel>>(){}.getType();
HashMap<String, AllUserDetailsResponseModel> user =
gson.fromJson(jsonObject, AllUserDetailsResponseModel);
AllUserDetailsKeyModel result = new AllUserDetailsKeyModel();
result.setResult(user);
return result;
}
}
The code in comments is my object model and u should replaceAllUserDetailsKeyModel with your model class and add this to the rest client like below:-
private Converter.Factory createGsonConverter() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(AllUserDetailsKeyModel.class, new UserDetailsDeserializer());
Gson gson = gsonBuilder.create();
return GsonConverterFactory.create(gson);
}
This the custom Convertor for Retrofit.
In your onResponse you just loop with hasmaps and get value by key and my model class looks like below:-
public class AllUserDetailsKeyModel {
private Map<String, AllUserDetailsResponseModel> result;
public Map<String, AllUserDetailsResponseModel> getResult() {
return result;
}
public void setResult(Map<String, AllUserDetailsResponseModel> result) {
this.result = result;
}
}
probably you need to give a Type T where T is your data Type and my model consists only of a hashmap and getters and setters for that.
And finally set Custom Convertor to retrofit like below:- .addConverterFactory(createGsonConverter())
Let me know if you need more clarifications.
Use GenericTypeIndicator to get List of Child Node from Firebase ArrayList structured DataBase
//Start of Code
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot snapshot){
GenericTypeIndicator<List<YourClassName>> t = new GenericTypeIndicator<List<YourClassName>>{};
List<YourClassName> messages = snapshot.getValue(t);
Log.d("Get Data Size", messages.size());
}
}
#Override
public void onCancelled(FirebaseError firebaseError){
Log.e("The read failed: ",firebaseError.getMessage());
}
});
your problem is why your code doesn't work.
this your code:
Firebase ref = new Firebase(FIREBASE_URL);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.e("Count " ,""+snapshot.getChildrenCount());
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
<YourClass> post = postSnapshot.getValue(<YourClass>.class);
Log.e("Get Data", post.<YourMethod>());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("The read failed: " ,firebaseError.getMessage());
}
})
you miss the simplest thing: getChildren()
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference reference = FirebaseAuth.getInstance().getReference("Donald Trump");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int count = (int) dataSnapshot.getChildrenCount(); // retrieve number of childrens under Donald Trump
String[] hairColors = new String[count];
index = 0;
for (DataSnapshot datas : dataSnapshot.getChildren()){
hairColors[index] = datas.getValue(String.class);
}
index ++
for (int i = 0; i < count; i++)
Toast(MainActivity.this, "hairColors : " + hairColors[i], toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
ArrayList<String> keyList = new ArrayList<String>();
mKeyRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
String temp = childDataSnapshot.getKey();
keyList.add(temp);
i = keyList.size();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
This code is working fine to add all firebase key into arraylist, you can do it with firebase values, of other static values.
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mMainMenuRef = mRootRef.child("tut_master");//main
DatabaseReference mSubMenuRef = mMainMenuRef.child("english");//sub
List<Tutorial> tutorialNames=new ArrayList<>();
mSubMenuRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
long id = ds.child("id").getValue(Long.class);
String name = ds.child("name").getValue(String.class);
Tutorial tut = new Tutorial();
tut.setTutId(id+"");
tut.setTutName(name);
tutList.add(tut);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
private FirebaseDatabase firebaseDatabase= FirebaseDatabase.getInstance();
private DatabaseReference databaseReference= firebaseDatabase.getReference();
private DatabaseReference mChildReference= databaseReference.child("data");
mChildReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
User commandObject = ds.getValue(User.class);
Log.d("TAG", commandObject.getMsg());
}
Toast.makeText(MainActivity.this,dataSnapshot.toString(),Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This will help you, you just have to create a model class containing String msg.
Use Gson is my favorite solution.
mFirebaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Type StringListType = new TypeToken<List<String>>(){}.getType();
List<String> td = new Gson().fromJson(dataSnapshot.getValue(), StringListType);
}
});
if you think the code to get TypeToken is unintuitive. You can write a class to contain all types you need. So next time, you can get those types quickly.
class TypeTokens{
static public final Type StringListType = new TypeToken<List<String>>(){}.getType();
static public final Type StringMapType = new TypeToken<Map<String, String>>(){}.getType();
static public final Type LongMapType = new TypeToken<Map<String, Long>>(){}.getType();
static public final Type DateMapType = new TypeToken<Map<String, Date>>(){}.getType();
}
Here goes my 2 cents contribution (in Kotlin):
private fun getData(childUid:String) {
refDB = firebaseDB.reference.child(MAIN_DATABASE_FOLDER).child(childUid)
if(childEventDataListener == null) {
childEventDataListener = object : ChildEventListener {
override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
for(snap in snapshot.children) {
val newParcel = snapshot.getValue(YourClassConverter::class.java)!!
}
}
override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) { }
override fun onChildRemoved(snapshot: DataSnapshot) { }
override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
override fun onCancelled(error: DatabaseError) {}
}
refDB.addChildEventListener(childEventDataListener!!)
}
}
The class YourClassConverter shall follow this rule as noted in the getValue header's comment shown below. I prefer to use this converter since I can control the default values passed when some of them are not defined in the firebase.
This method is used to marshall the data contained in this snapshot into a class of your choosing. The class must fit 2 simple constraints:
The class must have a default constructor that takes no arguments
The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized
An example class might look like:
class Message {
private String author;
private String text;
private Message() {}
public Message(String author, String text) {
this.author = author;
this.text = text;
}
public String getAuthor() {
return author;
}
public String getText() {
return text;
}
}
// Later
Message m = snapshot.getValue(Message.class);

Categories

Resources