【问题标题】:Wait until complete onChildAdded in firebase querys, Android等到在 Firebase 查询中完成 onChildAdded,Android
【发布时间】:2016-06-09 05:56:47
【问题描述】:

我是 Firebase 的新手,正在做一个简单的项目。我有一种方法可以从 Firebase 获取教师列表并将他们的电子邮件添加到 ArrayList 并返回。

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 Monitor 是这样的:

D/返回:[]

D/TEACHER:{number=1,name=Teacher,email=teacher@new.lk,subject=Physics}

D/ENTRY: : DATA teacher@new.lk

有什么办法可以等到完成那个onChildAdded方法..?

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

我也尝试过这种方式。但后来它停在了 inside 方法。

这里甚至没有去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;
}

【问题讨论】:

  • 等待异步操作是对线程的浪费。但如果你坚持:我的回答会告诉你两个选项:stackoverflow.com/questions/33203379/…
  • 先生,我阅读了您的帖子并尝试了您的方式。但这对我没有帮助。调用该方法后程序没有处理。有什么建议吗?
  • 我很确定我写的代码可以工作。但对你来说好消息是你总是可以服用那个答案中提到的红色药丸。无论如何,这是更好的方法。
  • 我昨天再次快速测试了信号量方法,它确实完全阻塞了应用程序。我想我第一次写它时在 Android 上进行了测试,但现在不确定了。但正如所说:无论如何,带有回调的方法是推荐的方法。现代互联网是异步的,您越早接受这一事实,您就能越早构建利用它的应用程序。
  • 感谢您再次查看。我没有使用它,而是使用了 Otto 库。 (square.github.io/otto) 它按我想要的方式工作

标签: java android firebase


【解决方案1】:
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){

}
}

这是一个非常基本的 otto 用法示例 - EventBus。从bus.post(o),你可以调用相关的订阅方法。

【讨论】:

  • 感谢您的宝贵时间,但您如何知道所有回调何时完成?每次您获得 Firebase 位置中每个节点的回调时,此代码都会触发事件。我正在寻找当所有子节点回调都是 rcvd 时收到通知的内容。
【解决方案2】:

已解决: 我使用了 http://square.github.io/otto/ 的 Otto EventBus 库,它对我有用

【讨论】:

  • 任何解释你如何使用事件总线?我处于同样的情况必须等待所有回电
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多