Reputation: 450
I'm currently developing an android app where I'm using firebase as database but when in got the variable in the onDataChange method and I assign them to a global variables I got null variables but when I call those variables in the onDataChange method they are not null.
public class PositionateMarkerTask extends AsyncTask {
public ArrayList<Location> arrayList= new ArrayList<>();
public void connect() {
//setting connexion parameter
final Firebase ref = new Firebase("https://test.firebaseio.com/test");
Query query = ref.orderByChild("longitude");
//get the data from the DB
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//checking if the user exist
if(dataSnapshot.exists()){
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
//get each user which has the target username
Location location =userSnapshot.getValue(Location.class);
arrayList.add(location);
//if the password is true , the data will be storaged in the sharedPreferences file and a Home activity will be launched
}
}
else{
System.out.println("not found");
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("problem ");
}
});
}
@Override
protected Object doInBackground(Object[] params) {
connect();
return null;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
System.out.println("the firs long is"+arrayList.get(0).getLongitude());
}
}
Upvotes: 3
Views: 7157
Reputation: 600116
Welcome to asynchronous programming, which messes up everything you always thought was true. :-)
Firebase retrieves/synchronizes with the database automatically in the background. The work happens on a separate thread, so you don't need and AsyncTask
. But unfortunately this also means you can't wait for the data.
I typically recommend that you reframe your code from "first do A, then to B" to "whenever we get A, we do B with it".
In your case, you want to get the data and then print the longitude of the first item. Reframed that is: whenever you receive data, print the longitude of the first item.
Query query = ref.orderByChild("longitude");
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
Location location =userSnapshot.getValue(Location.class);
arrayList.add(location);
}
System.out.println("the first long is"+arrayList.get(0).getLongitude()); }
else{
System.out.println("not found");
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("problem ");
}
});
A few things to note here:
if you're only interested in the first item, you can limit the query to one item: query = ref.orderByChild("longitude").limitToFirst(1)
. This will retrieve less data.
I recommend using addValueEventListener()
instead of addListenerForSingleValueEvent()
. The former will keep synchronizing the data. This means that if you insert/change the longitude of an item in the list, your code will automatically get retriggered and print the (potentially) new first item.
Upvotes: 9