【问题标题】:Firebase: How to capture data in real timeFirebase:如何实时捕获数据
【发布时间】:2014-11-21 01:49:26
【问题描述】:

我正在尝试以从单个事件调用的侦听器获取的方法返回数据。但是,看起来我要返回的对象是在实际的 return 语句之后填充的。我知道获取数据快照的调用是异步的,这就是发生这种情况的原因。我怎样才能避免这种情况?我试过信号量和原子布尔值,但它似乎锁定了我的应用程序。这是有问题的代码。

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 boolean 设置为 false,然后在侦听器中设置为 true,然后在返回之前有一段时间(boolean == false),但这会导致我的应用程序锁定。

【问题讨论】:

标签: android firebase


【解决方案1】:

您尝试做的是使 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 中内置的许多构造都依赖于这种模式。

【讨论】:

  • 很抱歉,这是一个超级老问题,但非常有用。你会如何定义回调类AwesomeCallback
  • 我通常定义一个内部类,但这是一个随意的选择。您只需要一个定义您从其他方法调用的函数的类。
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多