0

I'm developing a map application but I keep getting this error when I try to fetch latlng from Firebase, I don't understand it and don't know how to solve.

Error :

java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) at java.util.ArrayList.get(ArrayList.java:308) at fr.divdev.maphadev.MapsActivity.initMarkers(MapsActivity.java:120) at fr.divdev.maphadev.MapsActivity.onMapReady(MapsActivity.java:74) at com.google.android.gms.maps.zzak.zza(Unknown Source) at com.google.android.gms.maps.internal.zzaq.dispatchTransaction(Unknown Source) at com.google.android.gms.internal.maps.zzb.onTransact(Unknown Source)

The getLocationList() code:

public List < Location > getLocationList() {
    final List < Location > list = new ArrayList < > ();
    DatabaseReference f_database = FirebaseDatabase.getInstance().getReference().child("location");
    f_database.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child:
                dataSnapshot.child("Loisir").child("lieu").child("latlng").getChildren()) {
                double lat = Double.parseDouble(child.child("latitude").getValue().toString());
                double lng = Double.parseDouble(child.child("longitude").getValue().toString());
                list.add(new Location("location", new LatLng(lat, lng)));
                Log.e("erreur", "********");
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });
    return list;
}
AsthaUndefined
  • 1,111
  • 1
  • 11
  • 24
  • 1
    Which is the line with the exception? – Gabriele Mariotti Sep 30 '19 at 06:31
  • show this line 255. – Makarand Sep 30 '19 at 06:32
  • This is not the code for your exception as you are not accessing your list in this function. this exception comes when you access returned list from the function `getLocationList` – Mohit Dholakia Sep 30 '19 at 06:42
  • the line 255 is ArrayList.class.... –  Sep 30 '19 at 06:50
  • private void fastRemove(int var1) { ++this.modCount; int var2 = this.size - var1 - 1; if (var2 > 0) { System.arraycopy(this.elementData, var1 + 1, this.elementData, var1, var2); } –  Sep 30 '19 at 06:50
  • @JulienLrda can you share your implementation of `initMarkers()` method? – rbd_sqrl Sep 30 '19 at 06:53
  • past your complete code. including iteration on list – Atif AbbAsi Sep 30 '19 at 06:54
  • As `Invalid index 0, size is 0 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) ` suggests, your arraylist, which I suppose is the `ArrayList` of `Location`s is accessed somewhere when the arraylist is empty. – ravi Sep 30 '19 at 06:55
  • @JulienLrda The exception is not in the `getLocationList` method. It is at line **120** of `MapsActivity` in the `initMarkers` method. **Debug** this method and check why you are trying to get an element from an empty list. – Gabriele Mariotti Sep 30 '19 at 07:02

2 Answers2

0

After listener is added, since firebase need to fetch the data using network, the process will take time. So you cannot make a function that fetches from firebase db in remote machine and expect it to return the complete data. What you can do is call the function that need to be called after getLocationList() inside onDataChange()

public void getLocationList() {
    DatabaseReference f_database = FirebaseDatabase.getInstance().getReference().child("location");
    f_database.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            List < Location > list = new ArrayList < > ();
            for (DataSnapshot child:
                dataSnapshot.child("Loisir").child("lieu").child("latlng").getChildren()) {
                double lat = Double.parseDouble(child.child("latitude").getValue().toString());
                double lng = Double.parseDouble(child.child("longitude").getValue().toString());
                list.add(new Location("location", new LatLng(lat, lng)));
                Log.e("erreur", "********");
            }
            someFunction(list);
        }

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

Or you can also try onComplete() or onSuccess() etc. methods.

As a tip, instead of listening to the "location" node and childing later, its more efficient to listen on to the required node itself.

DatabaseReference f_database = FirebaseDatabase.getInstance().getReference().child("location");

DatabaseReference f_database = FirebaseDatabase.getInstance().getReference().child("location").child("Loisir").child("lieu").child("latlng");

and then

for (DataSnapshot child: dataSnapshot.child("Loisir").child("lieu").child("latlng").getChildren()) {

for (DataSnapshot child: dataSnapshot.getChildren()) {
...
}
npk
  • 1,512
  • 1
  • 13
  • 26
-1

list which is returned by the function is empty because firebase api call is asynchronous, hence return list; is executed before the api can get data.

Move return list; inside onDataChange function outside the for loop, then you'll have your data. Now in order to get asynchronous data try using asynctask or create an interface to return data. Hope this helps.

  • then the funciton will require something else to return, for the case forloop is not executed. hence `return list;` inside `onDataChange()` will never get called – npk Sep 30 '19 at 07:20
  • That is why I mentioned to use asyntask or make an interface for making network calls. Please read again. Thanks. – Akash Chauhan Oct 01 '19 at 08:02