2016-02-26 47 views
2

我是Firebase的新手,正在從事簡單的項目。我有一種方法可以從Firebase獲取教師名單,並將他們的電子郵件添加到ArrayList並返回。等待,直到完成onChildAdded在firebase querys,Android

public ArrayList<String> getTeacherList() { 
    temp = new ArrayList(); 

    Firebase node = ref.child("teachers"); 
    Query query = node.orderByChild("subject").equalTo(selected_subject); 

    query.addChildEventListener(new ChildEventListener() { 
     @Override 
     public void onChildAdded(DataSnapshot dataSnapshot, String s) { 

      Map<String,Object> value = (Map<String, Object>) dataSnapshot.getValue(); 
      Log.d("TEACHER"," "+value.toString()); 

      Iterator entries = value.entrySet().iterator(); 
      while (entries.hasNext()) { 
       Map.Entry thisEntry = (Map.Entry) entries.next(); 
       String key = (String) thisEntry.getKey(); 
       Object data = thisEntry.getValue(); 

       if(key.equals("email")) { 
        temp.add(data.toString()); 
        Log.d("ENTRY",": DATA "+data.toString()); 
       } 
      } 

     } 

     @Override 
     public void onChildChanged(DataSnapshot dataSnapshot, String s) { 

     } 

     @Override 
     public void onChildRemoved(DataSnapshot dataSnapshot) { 

     } 

     @Override 
     public void onChildMoved(DataSnapshot dataSnapshot, String s) { 

     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 

     } 
    }); 


    Log.d("RETURN", temp.toString()); 
    return temp; 
} 

此方法工作正常。但問題是這樣會在完成添加子項之前返回temp變量。

例如我的Android監視器是這樣的:

d/RETURN:[]

d /老師:{數= 1,姓名=老師,[email protected],主題=物理}

d/ENTRY:DATA [email protected]

有沒有辦法等到完全是onChildAdded方法..?

============================================== ===========================

我也嘗試過這種方式。但隨後它停止在內部方法。

即使它沒有去Log.d("TEACHER", " " + value.toString());標籤在這裏。

public ArrayList getTeacherList() throws InterruptedException { 
    temp = new ArrayList(); 

    Firebase node = ref.child("teachers"); 
    Query query = node.orderByChild("subject").equalTo(selected_subject); 

    semaphore = new Semaphore(0); 

    query.addChildEventListener(new ChildEventListener() { 
     @Override 
     public void onChildAdded(DataSnapshot dataSnapshot, String s) { 

      Map<String, Object> value = (Map<String, Object>) dataSnapshot.getValue(); 
      Log.d("TEACHER", " " + value.toString()); 

      Iterator entries = value.entrySet().iterator(); 
      while (entries.hasNext()) { 
       Map.Entry thisEntry = (Map.Entry) entries.next(); 
       String key = (String) thisEntry.getKey(); 
       Object data = thisEntry.getValue(); 

       if (key.equals("email")) { 
        setArrayList(data.toString()); 
        Log.d("ENTRY", ": DATA " + data.toString()); 
       } 
      } 
      semaphore.release(); 
     } 

     @Override 
     public void onChildChanged(DataSnapshot dataSnapshot, String s) { 

     } 

     @Override 
     public void onChildRemoved(DataSnapshot dataSnapshot) { 

     } 

     @Override 
     public void onChildMoved(DataSnapshot dataSnapshot, String s) { 

     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 

     } 
    }); 
    semaphore.acquire(); 
    return temp; 
} 
+0

等待異步操作是浪費線程。但是,如果你堅持:我的答案在這裏會告訴你兩個選項:http://stackoverflow.com/questions/33203379/setting-singleton-property-value-in-firebase-listener –

+0

先生,我讀你的文章,並嘗試在你的辦法。但是這並沒有幫助我。調用此方法後程序沒有處理。有什麼建議麼..? –

+0

我很確定我寫的代碼的作品。但對你而言,好消息是你可以隨時服用該答案中提到的紅色藥丸。無論如何,這是更好的方法。 –

回答

1

解決: 我用奧托EventBus圖書館從http://square.github.io/otto/和它的工作對我來說

+0

任何解釋你如何使用事件總線?我在同樣的情況下必須等待所有回電 –

+0

請參閱此答案:[Answer Below](http://stackoverflow.com/a/38542796/4882204) –

2
public class MainActivity extends AppCompatActivity{ 
public static Bus bus; 

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState);   
    bus = new Bus(ThreadEnforcer.MAIN); 
    bus.register(this); 

    //CALL TO LOAD DATA FROM FIREBASE 
    loadData(); 
} 

private void loadData(){ 
    DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference(); 
    mDatabase.child("my-data").addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      //CREATE YOUR OWN OBJECT USING RECEIVED DATA 
      MyObject o = new MyObject(); 
      //CALL FOR METHOD nextMethod() 
      bus.post(o); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 
      Log.d("Error", databaseError.toString()); 
     } 
    }); 
} 

@Subscribe 
private void nextMethod(MyObject o){ 

} 
} 

這是奧托的使用非常簡單的例子 - EventBus。從bus.post(o),您可以調用相關的訂閱方法。

+0

感謝您的時間,但您將如何知道所有回調完成了嗎?此代碼會在每次獲取Firebase位置中每個節點的回調時觸發事件。我正在尋找當所有子節點回調都是rcvd時得到通知的東西。 –