1

I have an application that is checking against points of interest stored in a Firebase database. Each user has their own specific interests in genres which affects what is displayed on the map.

To analyse these interests that each user has, I take their interests from the database and place them in a hashmap specific to the user. Within the user's constructor I call the setInterests() method which actually performs the setting of the data within the HashMap.

I also have a method within the User class that checks the contents of the user's interestMap for a specific genreID. If they have it, return true, if they don't, return false. I also check if the hashmap is empty, and if it is, I want to display all data. However, when the hasInterest() method is called, the user's interestMap has not yet been set. setInterets() is called in the User constructor, with the user instance being created in my MapActivity's onCreate.


User Constructor

public User(String username){
    this.username = username;
    interestMap = new HashMap<>();
    setInterests();
}

Has Interest Method

// Check if the user has the listed interest
public boolean hasInterest(final long genreId){
    String id = String.valueOf(genreId);

    System.out.println("Has Interest: " + interestMap);
    // If the user has no interests, display the listed interest
    if(interestMap.isEmpty()){
        Log.d(TAG, "User has  no interests, showing all " + interestMap.get(id));
        return true;
    }

    Object interest =  interestMap.get(id);
    // If the user does not have the listed interest, don't display it
    if(interest == null){
        Log.d(TAG, "User does not have interest in this, not showing data");
        return false;
    }
    Log.d(TAG, "User has interest in Genre"+ interestMap.get(id)+ ", showing data");
    return true;
}

Set Interests method

 public void setInterests() throws DatabaseException{

    mDatabase = FirebaseDatabase.getInstance().getReference("users/" + getUid()+"/interests");
    try{
        mDatabase.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for(DataSnapshot interestSnapshot: dataSnapshot.getChildren()){
                    String interestKey = interestSnapshot.getKey();
                    Object interestValue = interestSnapshot.getValue();

                    Log.d(TAG, "Key = " + interestKey + "; Value = " + interestValue);
                    push(interestKey, interestValue);
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w(TAG, "Could not access data: ", databaseError.toException());
                Log.d(TAG, "Error Code: " + databaseError.getCode());
            }
        });
    }catch(DatabaseException e){
        Log.w(TAG, "Database Exception " + e);
    }
    System.out.println(interestMap);
}

Map Activity On Create method

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        checkLocationPermission();
    }
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    Firebase.setAndroidContext(this);

    auth = FirebaseAuth.getInstance();
    user = new User(auth.getCurrentUser().getEmail());

Where the Has Interest method is called within the Maps OnLocationChanged

ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.d(TAG, "Inside onDataChange");
            for (final DataSnapshot poiSnapshot : dataSnapshot.getChildren()) {

                final String mPoiSnapshot = poiSnapshot.getKey();
                // Get data from Firebase
                final String mPoiTitle = (String) poiSnapshot.child("title").getValue();
                final String mPoiStory = (String) poiSnapshot.child("story").getValue();
                final long mPoiGenreID = (long) poiSnapshot.child("Genre/ID").getValue();
                final String mPoiGenreType= (String) poiSnapshot.child("Genre/Type").getValue();

                final POIGenre mPoiGenre = new POIGenre(mPoiGenreID, mPoiGenreType);

                if(user.hasInterest(mPoiGenreID)) {

For some reason, this hasInterest() is called before my User is actually created. I have tried creating my user within the OnLocationChanged method, where hasInterest() is actually called, as a debug method, but that didn't affect anything.

Here is my debug that is produced where I print out my interestMap's contents and what is in it when the hasInterest() method checks it.

 I/System.out: Has Interest: {}
 D/******* USER user@user.com: User has  no interests, showing all null
 I/System.out: Has Interest: {} 
 D/******* USER user@user.com: User has  no interests, showing all null
 I/System.out: Has Interest: {}
 D/******* USER user@user.com: User has  no interests, showing all null
 I/System.out: Has Interest: {}
 D/******* USER user@user.com: User has  no interests, showing all null
 D/******* USER user@user.com: Key = 1; Value = Historical
 I/System.out: {1=Historical}

At the end you can see that the Historical genre from my Firebase is being placed in the interestMap

Am I just missing something painfully obvious? Any help would be massively appreciated.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Data is loaded from the Firebase database asynchronously. This means that by the time you print the interests, the data hasn't been loaded yet. I recommend reading more about this in the top answers from this list: http://stackoverflow.com/search?tab=votes&q=%5bandroid%5d%5bfirebase-database%5d%20asynchronous – Frank van Puffelen Feb 14 '17 at 15:58
  • Ah, that clears it up, looks like I'm going to have to delve into some asynchronous wizardry. Thanks for the tip. – thetrainfiasco Feb 15 '17 at 09:59

0 Answers0