0

I have a problem with Firebase eventListeners. I am trying to get some data from a Firebase database but I cannot get results back. The problem is that my listeners are not running or giving results back. I have tried getting results with 2 different listeners (onGetDataListener, ValueEventListener). During debug the whole listener gets skipped and the debugger moves forward. I have added Log.d on all listener stages but none gets accessed.

public class Suggestionsfragment extends Fragment implements AdapterView.OnItemClickListener {
    private GooglePlaceList nearby;
    LinearLayout linearLayout;
    Double latitude;
    Double longitude;
    List<String> urlList;
    private List<String> interestList;
    private List<Double> latlong;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.suggestions, container, false);
        linearLayout = (LinearLayout) v.findViewById(R.id.main_layout);

        String placesKey = this.getResources().getString(R.string.places_key);
        interestList = new ArrayList<>();
        latlong = new ArrayList<>();
        nearby = null;
        FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
        FirebaseUser user = firebaseAuth.getCurrentUser();
        DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
        if (user != null) {

            DatabaseReference ref1 = databaseReference.child(user.getUid()).child("interest");
            readData(ref1, new OnGetDataListener() {
                @Override
                public void onSuccess(DataSnapshot dataSnapshot) {
                    Log.d("ONSUCCESS", "Success");
                    for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                        String interests = postSnapshot.getValue(String.class);
                        interestList.add(interests);
                    }
                }
                @Override
                public void onStart() {
                    //whatever you need to do onStart
                    Log.d("ONSTART", "Started");
                }

                @Override
                public void onFailure() {
                Log.d("ONFAILURE", "Failure");
                }
            });
            databaseReference.child(user.getUid());
            databaseReference.child("location");
            databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    Log.d("ONDATACHANGED", "listener2 entered");
                    try {
                        if (dataSnapshot.getValue() != null) {
                            for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                                Double loc = postSnapshot.getValue(Double.class);
                                latlong.add(loc);
                            }

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });
        }
        latitude = latlong.get(0);
        longitude = latlong.get(1);

        int radius = 500;
        urlList = generateUrlList(interestList, longitude, latitude, radius, placesKey);
        if (placesKey.equals("PUT YOUR KEY HERE"))
            Toast.makeText(getActivity(), "You haven't entered your Google Places Key into the strings file.  Dont forget to set a referer too.", Toast.LENGTH_LONG).show();
        else {
            PlacesReadFeed process = new PlacesReadFeed();
            process.execute(urlList);

        }

        return v;
    }
    ...
}
Daniel
  • 2,355
  • 9
  • 23
  • 30

2 Answers2

1

There are a number of things to fix.

This code isn't right:

databaseReference.child(user.getUid()); // does nothing
databaseReference.child("location"); // does nothing
databaseReference.addListenerForSingleValueEvent(...);

You probably want:

databaseReference.child(user.getUid()).child("location")
    .addListenerForSingleValueEvent(...);

You say During debug the whole listener is getting skipped and the debugger moves forward. That is because the listener callbacks fire asynchronously, after the query is sent to the Firebase servers and a response received (more details here). That means that when these statements execute:

latitude = latlong.get(0);
longitude = latlong.get(1);

latlong will not contain valid data because onDataChange() has not yet executed.

If your listeners never fire, it's likely that either you have no internet connection, or the security rules are not set to allow the data to be read. The security rules are explained here. You should add debug output to onCancelled():

@Override
public void onCancelled(DatabaseError databaseError) {
    Log.e("CANCELLED", databaseError.toException());
}

I don't recognize OnGetDataListener(). Is that a class you defined?

Community
  • 1
  • 1
Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • I used to have the datareference as you indicated with no result: databaseReference.child(user.getUid()).child("location") .addListenerForSingleValueEvent(...); i have found the onGetDataListener from this post: http://stackoverflow.com/questions/42621911/firebase-ondatachange-not-entered which seemed relevant to my problem, but it did not help sadly. – Dimitris Karakatsanis Mar 17 '17 at 01:38
  • You were right, asynchronous listener callback is probably the issue. I have commented out the possible variables that would lead to Null-pointer and the onDataChanged runs 3 secs after execution. I guess i need to figure out a way to retrieve Firebase data before the rest of the code executes. – Dimitris Karakatsanis Mar 17 '17 at 02:15
0

I managed to work with Async firebase fetching by setting up my application inside the onDataChanged:

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.suggestions, container, false);
    linearLayout = (LinearLayout) v.findViewById(R.id.main_layout);

    final String placesKey = this.getResources().getString(R.string.places_key);
    interestList = new ArrayList<>();
    latlong = new ArrayList<>();
    nearby = null;
    FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
    FirebaseUser user = firebaseAuth.getCurrentUser();

    if (user != null) {
        DatabaseReference ref1 = FirebaseDatabase.getInstance().getReference().child(user.getUid());
        readData(ref1, new OnGetDataListener() {
            @Override
            public void onSuccess(DataSnapshot dataSnapshot) {
                Log.d("ONSUCCESS", "Success");
                for (DataSnapshot postSnapshot : dataSnapshot.child("interest").getChildren()) {
                    String interests = postSnapshot.getValue(String.class);
                    interestList.add(interests);
                }
                for (DataSnapshot postSnapshot : dataSnapshot.child("location").getChildren()) {
                    Double loc = postSnapshot.getValue(Double.class);
                    latlong.add(loc);
                }

                latitude = latlong.get(0);
                longitude = latlong.get(1);

                int radius = 500;
                urlList = generateUrlList(interestList, longitude, latitude, radius, placesKey);
                PlacesReadFeed process = new PlacesReadFeed();
                process.execute(urlList);
            }

            @Override
            public void onStart() {
                //Whatever you want to do on start
                Log.d("ONSTART", "Started");
            }

            @Override
            public void onFailure() {
                //Whatever you want to do in case of failure
                Log.d("ONFAILURE", "Failure");
            }
        });
    }

    return v;
}

The readData and OnGetListener interface:

public void readData(DatabaseReference ref, final OnGetDataListener listener) {
    listener.onStart();
    ref.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            listener.onSuccess(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            listener.onFailure();
        }
    });

}

interface OnGetDataListener {
    //make new interface for call back
    void onSuccess(DataSnapshot dataSnapshot);
    void onStart();
    void onFailure();
}