2016-02-26 48 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时得到通知的东西。 –