2017-01-13 5 views
1

AndroidスタジオでFirebaseをDBとして使用しているアプリを開発していますが、難しい問題があります。私はDBへの実際のクエリを行う補助クラスから 'pregunta'オブジェクトを取得するフラグメントを持っています。問題は、リスナーが別のスレッドを起動してイベントを待つことですが、その間にメソッドは処理を継続し、null値を返します。Firebase DBとAndroid:アクティビティ/フラグメントクラスと異なるFirebaseのクラスを使用した同期の欠如

この非同期を回避する方法やこれを実装するためのよりよい方法についてのアイデアはありますか?ありがとう!!

フラグメントクラス:

mPregunta = mSesionManager.getPregunta(id_pregunta_actual); 
    TextView view_pregunta = (TextView)view.findViewById(R.id.titulo_pregunta); 
    view_pregunta.setText(mPregunta.getTxt_pregutna()); 

補助クラスメソッド:

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; 
} 

ログ:

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 
+0

あなたでし '公共pregunta getPregunta(長いID、ChildEventListenerリスナー){// ... query.addChildEventListener(リスナー)。 // ..} 'そしてあなたのフラグメントクラスを更新してください – Linxy

答えて

0

あなたはそのように行うことはできません。 Firebase Listenerは非同期なので、Firebaseがデータをロードする前にリターンします。

私もそれを試しましたが、それを簡単に達成する方法はありません。しかし、アプリケーションが起動すると、すべてのデータをプリロードし、ハッシュマップやArrayListなどに保存することができます。次に、アクティビティのリストとすべてのフラグメントを簡単に取得できます。

これは私のやり方であり、完全に機能します。あなたがそれについてもっと知りたいなら、教えてください。

+0

答えHhornのおかげで、私はそれがいくつかのシナリオではうまくいくと思います。しかし、私はFirebaseのnonSQL DBを実際にテストしており、キーではない他の属性に基づいて要素を選択する方が簡単だと思っていましたが、HashMapsや配列の使用はこれを複雑にします...私は私はそれをうまくやることができれば。 –

1

リスナーをFirebaseに登録すると、その登録は実行中のスレッドをブロックすることなく行われます。リスナーが何をしているのかは、「そのデータの中の何かが利用可能になったら、すぐには起こりませんが、後であることを理解しています。

これらのリスナーの仕組みの周りにアプリケーションを設計する必要があります。リスナーからの受信情報に反応し、スレッド上のスレッドをブロックしないでください。

+0

コードを補助クラスからフラグメントクラスに移動しました。少なくとも、アプリケーションはDBから取得するコンテンツを表示します。しかし、ユーザーの観点からは最適ではないため、フラグメントがFirebaseを待っている(またはリスニングしている)ため、実際にデータを直接取得するのではなくTextViewを塗りつぶすため、「点滅」があります。よりスムーズな視覚化の仕方に関するアイディア –

+0

結果を待っている間、スピナーやトランジションビューを表示します。 –

1

私が最後にしたのは、ArrayListsを使用したホーホンの提案に基づいています。パラメータに基づいてさまざまな要素を選択する必要があるため、アダプタに渡して画面に表示できる別の配列を返す基本的な検索アルゴリズムメソッドを実行しました。

ロード

@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); 

      } 

検索:

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; 
    } 
関連する問題