AnonymousAlias
AnonymousAlias

Reputation: 1399

Android with Firebase - NullPointerException when trying to populate list

I am getting a null pointer exception (have tested 1 instead of i here)

This is the method

   public String getLat(int i) {
        fillDriverList();
        arrayLat.get(i);
        return"0.000";

    }

This is where it is called from in separate activity

 AdminActivity appState = new AdminActivity();
                latString = appState.getLat(i);

Here is the fill method, which is printing out the drivers names so appears to be filling the list, but then is null for some reason in my getLat method??

public void fillDriverList() {

        //Creating firebase object
        Firebase ref = new Firebase(Config.FIREBASE_URL);   

        //adding a value event listener so if data in database changes it does in textview also not needed at the minute
        ref.child("Driver").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {
                arrayLat = new ArrayList<String>();

                for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                    Driver d = postSnapshot.getValue(Driver.class);

                    System.out.println("data snapshot Drivers name is -------------------> "+d.getName());

                    arrayLat.add(Double.toString(d.getLat()));


                }

            }

            /************had to implement this method****************/
            @Override
            public void onCancelled(FirebaseError firebaseError) {
                System.out.println("The read failed: " + firebaseError.getMessage());

            }
        }); 

    }

NOTE When I pass it like this

intent.putStringArrayListExtra("arrayLat", arrayLat);

there is no problem using it in the other actvity like this

arrayLat = I.getStringArrayListExtra("arrayLat");

Although the values I use then in the next activity are stored values and do not update when my information(latitude) in firebase changes.

Thanks

Upvotes: 0

Views: 619

Answers (2)

Debanjan
Debanjan

Reputation: 2836

The problem that is visible through naked eye, is that, the list is being populated in a listener or callback, and you are treating the whole thing as synchronous. Look over here

ref.child("Driver").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {
                arrayLat = new ArrayList<String>();

                for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                    Driver d = postSnapshot.getValue(Driver.class);

                    System.out.println("data snapshot Drivers name is -------------------> "+d.getName());

                    arrayLat.add(Double.toString(d.getLat()));


                }

            }

            /************had to implement this method****************/
            @Override
            public void onCancelled(FirebaseError firebaseError) {
                System.out.println("The read failed: " + firebaseError.getMessage());

            }
        }); 

You are populating arrayLat inside onDataChange(DataSnapshot snapshot)

So, the fact is that since this is a callback the line arrayLat.get(i) is called even before the listener is fired and arrayLat is populated. Hope you got it. There are several ways to tackle this. You can create another interface to handle the callback or can directly write your code inside the callback. I will just write a simple solution. Change your code to this. First create an interface,

public interface SnapshotListener{
    void onListFilled(ArrayList<String> arrayLat);
    void onFailure();
}
    public void getLat(int i, SnapshotListener listener) {
            fillDriverList(listener);
            //arrayLat.get(i);
            //return"0.000";

        }

Now change the other method to this.

public void fillDriverList(SnapshotListener listener) {

        //Creating firebase object
        Firebase ref = new Firebase(Config.FIREBASE_URL);   

        //adding a value event listener so if data in database changes it does in textview also not needed at the minute
        ref.child("Driver").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {
                arrayLat = new ArrayList<String>();

                for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                    Driver d = postSnapshot.getValue(Driver.class);

                    System.out.println("data snapshot Drivers name is -------------------> "+d.getName());

                    arrayLat.add(Double.toString(d.getLat()));


                }
                if(listener != null){
                    listener.onListFilled(arrayLat);
                }

            }

            /************had to implement this method****************/
            @Override
            public void onCancelled(FirebaseError firebaseError) {
                System.out.println("The read failed: " + firebaseError.getMessage());
             if(listener != null){
                    listener.onFailure();
                }
            }
        }); 

    }

Now change

AdminActivity appState = new AdminActivity();
                latString = appState.getLat(i);

to this

appState.getLat(i, new SnapshotListener{
  public void onListFilled(ArrayList<String> arrayLat){
    AdminActivity appState = new AdminActivity();
                    latString = arrayLat;
}
    public void onFailure(){
     //go crazy
}
});

The codes are directly written in SO, so there may be some syntax errors.

Upvotes: 1

redAllocator
redAllocator

Reputation: 735

Driver Object have to check it

            for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                Driver d = postSnapshot.getValue(Driver.class);
                if(d!=null ){
                    arrayLat.add(Double.toString(d.getLat()));
                }
            }

Upvotes: 0

Related Questions