Francisco Jose Galan
Francisco Jose Galan

Reputation: 23

Firebase DB and Android: Lack of synchronism using a class for Firebase different from the activity/fragment class

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

Answers (3)

Francisco Jose Galan
Francisco Jose Galan

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

Doug Stevenson
Doug Stevenson

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

Hhorn
Hhorn

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

Related Questions