0

I have tried to get data from Firebase database and save the data into a global variable(mExampleHashMap) so that I can use it other places like on windowinfoclick listener. However, the data is only valid in the event listener, and I cannot get those data out of it. Seems it is related with variable scope so I tried to make it final on that global variables but still doesnt work. How can I save data in anonymous interface to local main variables?

final HashMap<Marker, Example> mExampleHashMap = new HashMap<>();
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setMyLocationEnabled(true);
    mMap.getUiSettings().setMyLocationButtonEnabled(true);

    // Get data from firebase database
    mDatabase = FirebaseDatabase.getInstance();
    mDatabaseReference = mDatabase.getReference();
    mDatabaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot d : dataSnapshot.getChildren()) {
                String name = (String) d.child("example").getValue();
                String x = (String) d.child("x").getValue();
                String y = (String) d.child("y").getValue();

                mExample = new Example(example, x, y);
                if (mExample != null) {
                    Marker marker = mMap.addMarker(new MarkerOptions().position(new LatLng(Double.parseDouble(x), Double.parseDouble(y))).title(name));
                    mExampleHashMap.put(marker, mExample );
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });

    // When I tried to use data out of the event listener, the variable is empty.
    Log.d(TAG, "onMapReady: mExampleHashMap: " + mExampleHashMap.size());

}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
CS Geek
  • 3
  • 1
  • As Doug answered, the problem is that when your `Log.d(TAG, "onMapReady: mExampleHashMap: " + mExampleHashMap.size());` the `onDataChange` hasn't been called yet. Any code that needs the data from the database needs to be inside `onDataChange` or be called from there. Also see https://stackoverflow.com/questions/50434836/getcontactsfromfirebase-method-return-an-empty-list/50435519#50435519 – Frank van Puffelen Jun 13 '20 at 03:45

1 Answers1

1

It's not the scope of the variable at all. You're just logging the value before the data is ready. All Firebase APIs are asynchronous and finish some time after you add the listener with addValueEventListener. The callback is only invoked when the database query is complete, and then again for every change after that.

The value of mExampleHashMap can be use anywhere in scope where the compiler allows -- it just doesn't have the value you want until after the callback is invoked.

Read about why the Firebase APIs are asynchronous.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441