Reputation: 23
I'm developing an app in Android Studio using Firebase as DB and I've a tricky issue. I have a fragment that gets a 'pregunta' object from an auxiliary class in which I do the actual query to the DB. The issue is that the listener launches a separate thread to wait for the event, but in the meantime the method continues processing and returns a null value.
Any ideas on how to avoid this asynchronism or a better way to implement this? Thanks!!
Fragment class:
mPregunta = mSesionManager.getPregunta(id_pregunta_actual);
TextView view_pregunta = (TextView)view.findViewById(R.id.titulo_pregunta);
view_pregunta.setText(mPregunta.getTxt_pregutna());
Auxiliary class method:
public pregunta getPregunta(long id){
mp.setId_pregunta(id);
Query query = mDB_Cuestionario.child("Tabla_Preguntas").orderByChild("id").equalTo(id);
query.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
mp.setTxt_pregutna(dataSnapshot.child("txt").getValue().toString());
Log.e("FBHELPER", "ID LISTENER: "+mp.getId_pregunta());
Log.e("FBHELPER", "TXT LISTENER: "+mp.getTxt_pregutna());
}
[-- rest of code --]
});
Log.e("FBHELPER", "TXT RESPUESTA: "+mp.getTxt_pregutna());
return mp;
}
Logs:
The method returns null value:
01-13 17:16:52.101 8994-8994/com.example.fran.cuestionario E/FBHELPER: TXT RESPUESTA: null
1 second later, the Event occurs, but I can't return the value.
01-13 17:16:53.497 8994-8994/com.example.fran.cuestionario E/FBHELPER: ID LISTENER: 0
01-13 17:16:53.497 8994-8994/com.example.fran.cuestionario E/FBHELPER: TXT LISTENER: TEST VALUE
Upvotes: 1
Views: 190
Reputation: 23
What I finally did is based on Hhorn suggestion of using ArrayLists. As I needed to select various elements based on a parameter, I just did a basic search algorithm method that returns another array that I can pass to an adapter to show it on the screen.
Load
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
respuesta r = new respuesta(
Integer.valueOf(dataSnapshot.child("id_po").getValue().toString())
, String.valueOf(dataSnapshot.child("txt").getValue().toString())
);
mSesionManager.mArrayRespuestas.add(r);
}
Search:
public ArrayList<respuesta> queryRespuestasFB(long id_pregunta_origen){
ArrayList<respuesta> respuestas_seleccionadas = new ArrayList<respuesta>();
for(respuesta r : mArrayRespuestas){
if (r.getId_pregunta_origen()==id_pregunta_origen){
respuestas_seleccionadas.add(r);
//Log.e("SM", "Respuesta Query: "+ r.toString());
}
}
return respuestas_seleccionadas;
}
Upvotes: 1
Reputation: 317372
When you register a listener with Firebase, that registration happens without blocking the thread that's running. What that listener is doing is saying: "When something in that data becomes available, let me know - I understand that it will not happen right away, but some time later".
You must design your app around the way these listeners work. You must react to the incoming information from listeners, not block any threads on it.
Upvotes: 1
Reputation: 223
You can't do it that way. The Firebase Listener is asynchronous, therefore it will return before Firebase load the data.
I tried that too and there is no way to accomplish it that easy. But you can preload all the data when the app starts and save it in a hashmap or ArrayList etc. Then you can easily retrieve a list in the Activity and all there fragments.
That's the way I do it and it works perfectly. If you want to know more about it, tell me.
Upvotes: 0