0

I'm unable to retrieve the data which is nested inside "Leagues" and "Season".

In the database below, I cannot retrieve Season 2016/2017 points and results.

I am able to access the data that is not nested, such as Email and Username without problems

"Users" : 
    "User1" : {
      "Email" : "dfs@sdf.com",
      "Last_login" : "5:15pm",
      "Username" : "Test",
      "Leagues" : {
        "FootballLeague" : true,
        "CricketLeague" : true
      },
      "Season" : {
         "2017" : {
               "Points" : 5,
               "Results" : 2
               "newdata" : {
                     "randomdata1: data1",
                     "randomdata2: data2"
                           },
                 }
         "2018" : {
                "Points" : 7,
                "Results" : 2
      }
}

The following class is what I'm using to store data as objects:

public class Users {

private String Username;
private String Email;
private String Last_login;
private Map<String, Boolean> Leagues;
private Map<String, thisSeason> Season;

public Users() {

}

//All getters and setters for the strings. 

public Map<String, Boolean> get_joined_Leagues() {
   return Leagues;
}

public void set_joined_Leagues(Map<String, Boolean> leagues) {
  Leagues = leagues;
}


public Map<String, thisSeason> getSeason() {
   return Season;
}

public void set_thisSeason(Map<String, thisSeason> season) {
  Season = season;
}

public static class thisSeason {
private int Points;
private int Results;
private Map <String, thisNewData> newdata;

    public thisSeason() {
    }

    public int getthisSeason_results() {
        return Results;
    }

    public void setthisSeason_results(int resultsin) {
        Results = resultsin;
    }

    public int getthisSeason_points() {
        return Points;
    }

    public void setSeason_points(int Pointsin) {
        Points = Pointsin;
    }

    public Map<String, thisNewData> getNewData() {
   return newdata;
    }

    public void set_thisNewData(Map<String, thisNewData> newdata_in) {
    newdata= newdata_in;
    }

    public static class thisNewData {
      private String randomdata1;
      private String randomdata2;

      //Getters and Setters
      }

Here is part of my Java class where I access the Database:

    List<Users> usersList= new ArrayList<Users>();
DatabaseReference fbDB = FirebaseDatabase.getInstance().getReference();

        fbDB.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            if (dataSnapshot.exists()) {

                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    Users C = ds.getValue(Users.class);
                    usersList.add(C);

                    System.out.println(C.getSeason().getthisSeason_points()); //ERROR occurs here - null object reference

                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });


}

I get a null object reference error as shown in the code above.

Also, on a slight side note - I'm aware my implementation for getting Leagues is incorrect. How can I retrieve the keys instead?

PSLDev
  • 77
  • 6
  • Usually inside my onDataChange method, I use String string = datasnapshot.getValue(String.class); Textview.setText(string); to fetch data. – Infinite Loops Oct 08 '17 at 10:29

1 Answers1

0

The main problems that I found in your code:

First, your Leagues object: Well, it should not be a custom object at all, if it stays in the current structure, but a Map. This is the map object - a collection which has a key, and a value, just like a child in the Realtime Database.

If a league name (=key) didn't have a true (=value) next to it - the names could have been stored in String variables, but this is not the case, because every child in the Realtime Database must have a value, and storing a "dummy" value next to a league name makes each league a part of a Map. This current "dummy" is a boolean, and that's why this will be the leagues' data type:Map<String, Boolean> leagues.


Second, your Season object: You are confusing between one season and many seasons. Your child - "Season" actually stores a lot of seasons. Thats why this case will be similar to the one above - each season's time is the key and the season itself is the value.


Therefore, the User class's variables should be:

private String Username;
private String Email;
private String Last_login;
private Map<String,Boolean> Leagues;
private Map<String, Season> Seasons;
Tal Barda
  • 4,067
  • 10
  • 28
  • 53
  • I have made the changes to my User class as you suggested above, but I still receive the null object reference error when trying to access the nested data. Same place as where I've commented "ERROR" in my code, I'm trying to access it like this... C.getSeason().getthisSeason_points(); – PSLDev Oct 07 '17 at 13:48
  • Please update your code and the current data structure in the question, it will be easier to help you this way. – Tal Barda Oct 07 '17 at 14:08
  • I've made updates to my the JSON and code to reflect what I have now. – PSLDev Oct 07 '17 at 14:52
  • Unfortunately not, I'm not sure how I can adapt the example you linked with my work here because I am trying to store the whole User object in an ArrayList then access individual data (or keys). – PSLDev Oct 07 '17 at 15:15
  • Please try to remove (just for checking) the Season variable from the object and the database, and see if it works. Maybe it has something to do with it. Also, please look at this post: https://stackoverflow.com/questions/36475470/nested-lists-in-firebase . The question is very much like yours, and it worked there. Maybe I have missed something, but I'm pretty sure this is the right way. – Tal Barda Oct 07 '17 at 16:55
  • I have just debugged it and seen that Map is working and Leagues are being stored. However, for thisSeason nothing is being stored for the object. – PSLDev Oct 07 '17 at 17:39
  • Also, have to keep Season there as I need to group Points and Results by year. – PSLDev Oct 07 '17 at 18:07
  • Having debugged it again, the points and result values are now being stored, but how do I access them from my ValueEventListener? Also, I've added a deeper layer to the nesting (Please see edit to JSON - named it random data for now, but I will be adding data here soon). How would I retrieve the data here? Many thanks! – PSLDev Oct 07 '17 at 18:46
  • First, if you need to retrieve the data only once at a time and not listening to it, than your listener should be "addListenerForSingleValueEvent" instead of your current listener. Now, what do you mean by how can I access them? I guess that converting the Map object to a list is an option. And about the "new data" thing - I think that creating a new object for "results" with the necessary properties would be a good approach, instead of just "int". – Tal Barda Oct 08 '17 at 01:40
  • I have changed the listener as suggested. By accessing I mean how to retrieve the results/points, as "C.getSeason().getthisSeason_points()" does not work in my listener. What would be the best way to convert to a list? Finally with regards to new data, it comes under '2017'. Please see my Object class, I've edited it. Not sure if this is the correct implementation. – PSLDev Oct 08 '17 at 14:26
  • I'm now able to print the 'points' and 'results' Struggling now with the new data. When debugging, it appears as null with the structure shown in the updated Java object code – PSLDev Oct 08 '17 at 15:37
  • If you will have more than one `newData`, try to store them in a Map: `Map newData`. If you have only one in each `season `, try to store only `randomdata1 ` and `randomdata2 ` directly under a `season ` instead, without using `thisNewData ` object. – Tal Barda Oct 08 '17 at 15:44
  • I will have multiple newData. As in my updated Java class in the OP, I've tried the Map you have suggested. But whilst debugging, it is just showing 'null', whereas Points and Results are storing the correct value. – PSLDev Oct 08 '17 at 15:57
  • I have created another question to specify latest issue. Will mark this as the correct answer. Thanks! – PSLDev Oct 08 '17 at 18:54