Firebase:如何实时捕获数据

时间:2014-11-21 01:49:27

标签: android firebase

我试图在一个方法中返回数据,我从一个侦听器获取单个事件调用。但是,看起来我返回的对象正在实际返回语句之后填充。我知道获取数据快照的调用是异步的,这就是为什么会发生这种情况。我怎么能避免这个?我尝试过Semaphores和Atomic Booleans,但它似乎只是锁定了我的应用程序。这是有问题的代码。

static User getUser(String uid){
    /**** created final object here for returning ****/
    final User returnUser = new User();

    Firebase userRef = new Firebase("<firebase-url>/users/"+uid+"/");

    userRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.d("MT", "attempting to instantiate user");
            User tempUser = dataSnapshot.getValue(User.class);

            /**** preparing object for return ****/
            returnUser.setNickname(tempUser.getNickname());
            returnUser.setAge(tempUser.getAge());
            returnUser.setEmail(tempUser.getEmail());
            returnUser.setHeight(tempUser.getHeight());
            returnUser.setSex(tempUser.getSex());
            returnUser.setWeight(tempUser.getWeight());

            //This logs actual information
            Log.d("MT", returnUser.getNickname() + " =======INSTANTIATED=======."); 
            Log.d("MT", returnUser.getEmail());
            Log.d("MT", new Double(returnUser.getAge()).toString());
            Log.d("MT", new Double(returnUser.getHeight()).toString());
            Log.d("MT", returnUser.getSex());
            Log.d("MT", new Double(returnUser.getWeight()).toString());
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            Log.d("MT", "Something went wrong.");
        }
    });
    Log.d("MT", returnUser.getNickname());    //This logs an empty string.
    return returnUser;
}

注意:我已经尝试将Atomic布尔值设置为false,然后在侦听器中设置为true,然后在返回之前使用while(boolean == false),但这会导致应用程序的锁定。

1 个答案:

答案 0 :(得分:4)

您尝试执行的操作是使Firebase同步。

这可能是可能的,但这是一个非常糟糕的主意。它冒着在主线程上进行网络操作的风险。一种让Android非常脾气暴躁的模式。请参阅doing network stuff on a separate thread上的一般指南。

所以,我已经确定在不同的线程上做网络工作很好,我有个好消息。 Firebase已经自动执行此操作!指定回调,就像在AsyncTask中一样。

更改您的getter以接受回调作为参数。

public void getUser(String uid, AwesomeCallback callback){

    Firebase userRef = new Firebase("<firebase-url>/users/"+uid+"/");

    userRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.d("MT", "attempting to instantiate user");
            User returnUser = new User();
            User tempUser = dataSnapshot.getValue(User.class);

            /**** preparing object for return ****/
            returnUser.setNickname(tempUser.getNickname());
            returnUser.setAge(tempUser.getAge());
            returnUser.setEmail(tempUser.getEmail());
            returnUser.setHeight(tempUser.getHeight());
            returnUser.setSex(tempUser.getSex());
            returnUser.setWeight(tempUser.getWeight());

            //This logs actual information
            Log.d("MT", returnUser.getNickname() + " =======INSTANTIATED=======."); 
            Log.d("MT", returnUser.getEmail());
            Log.d("MT", new Double(returnUser.getAge()).toString());
            Log.d("MT", new Double(returnUser.getHeight()).toString());
            Log.d("MT", returnUser.getSex());
            Log.d("MT", new Double(returnUser.getWeight()).toString());

            callback.doCallback(returnUser);
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            Log.d("MT", "Something went wrong.");
        }
    });
}

然后,从回调函数

开始工作
public class SomeAwesomeActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        someObject.getUser("uid123", new AwesomeCallback() {
            @Override
            public void doCallback(User user) {
                // Do cool stuff with that user object here
            }
        });
    }
}

如果你过去没有做过很多回调编程,那就有点奇怪了,需要一些时间来适应它。但是,一旦掌握了它,Android开发就会顺利进行。 Android SDK中内置的许多构造都依赖于这种模式。