-1

This activity displays geofences to the map. They're added as objects to an arraylist and then used by initArea() and are shown on the map. My issue is initArea() runs before onDataChange() so nothing is added to the arraylist and a null pointer exception is thrown. I want onDatachange() to run first so that the arraylist is populated. Thanks in advance :)

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GeoQueryEventListener {

    private static final String TAG = "Maps";
    private GoogleMap mMap;
    private LocationRequest locationRequest;
    private LocationCallback locationCallback;
    private FusedLocationProviderClient fusedLocationProviderClient;
    private Marker currentLocation;
    private DatabaseReference locationRef;
    private GeoFire geofire;
    private List<LatLng> geoFence;
    ArrayList<geofenceObj> geoTemp = new ArrayList<>();


    private String userID;


    private FirebaseDatabase mFirebaseDatabase;
    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;
    private DatabaseReference myRef;
    private int check;


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

        mAuth = FirebaseAuth.getInstance();
        mFirebaseDatabase = FirebaseDatabase.getInstance();
        myRef = mFirebaseDatabase.getReference();
        FirebaseUser user = mAuth.getCurrentUser();
        userID = user.getUid();

        mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                } else {
                    // User is signed out
                    Log.d(TAG, "onAuthStateChanged:signed_out");
                }

            }
        };

        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // This method is called once with the initial value and again
                // whenever data at this location is updated.
                showData(dataSnapshot);

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });


        Dexter.withActivity(this)
                .withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {

                        buildLocationRequest();
                        buildlocationcallback();
                        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MapsActivity.this);

                        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
                        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                                .findFragmentById(R.id.map);
                        mapFragment.getMapAsync(MapsActivity.this);


                        initArea();
                        settingGeofire();
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        Toast.makeText(MapsActivity.this, "Permissions not enabled ", Toast.LENGTH_SHORT).show();

                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {

                    }
                }).check();

    }


    private void showData(DataSnapshot dataSnapshot) {
        geoTemp.clear();
        for(DataSnapshot i : dataSnapshot.getChildren()) {


            for(int j=1; j<=dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
                String ID = String.valueOf(j);

                if (i.child(userID).child(ID).getValue() != null) {
                    geofenceObj geofence = new geofenceObj();
                    geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
                    geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
                    geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
                    geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());

                    geoTemp.add(geofence);
                    Log.d(TAG, "Added " + geofence.getName());
                }
            }
        }

    }

    private void initArea() {

        geoFence = new ArrayList<>();
        geoFence.add(new LatLng(0, 0));

        for(int i = 0; i <= geoTemp.size(); i++){
            geoFence.add(new LatLng(geoTemp.get(i).getLat(), geoTemp.get(i).getLat()));
        }
        Log.d(TAG, "Initialised Area");
    }
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Ryan
  • 3
  • 1

1 Answers1

0

You can't change the order in which asynchronous data is loaded. But what you can change is when you initialize the map that depends on the data. So move the call to initArea() into the onDataChange (or the showData) method, so that is runs after the data has been loaded.

private void showData(DataSnapshot dataSnapshot) {
    geoTemp.clear();
    for(DataSnapshot i : dataSnapshot.getChildren()) {
        for(int j=1; j<=dataSnapshot.child("users").child(userID).getChildrenCount(); j++) {
            String ID = String.valueOf(j);

            if (i.child(userID).child(ID).getValue() != null) {
                geofenceObj geofence = new geofenceObj();
                geofence.setName(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getName());
                geofence.setRadius(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getRadius());
                geofence.setLat(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLat());
                geofence.setLng(Objects.requireNonNull(i.child(userID).child(ID).getValue(geofenceObj.class)).getLng());

                geoTemp.add(geofence);
                Log.d(TAG, "Added " + geofence.getName());
            }
        }
    }
    // Now that the data is loaded and processed, we can initialize the map
    initArea();
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807