【问题标题】:can't get values out of ondatachange method无法从 ondatachange 方法中获取值
【发布时间】:2016-07-19 10:59:45
【问题描述】:

我目前正在开发一个 android 应用程序,我在其中使用 firebase 作为数据库,但是当在 onDataChange 方法中获取变量并将它们分配给全局变量时,我得到了 null 变量,但是当我在 onDataChange 中调用这些变量时方法它们不为空。

public class PositionateMarkerTask extends AsyncTask {
    public ArrayList<Location> arrayList= new ArrayList<>();
    public void connect() {
        //setting connexion parameter
        final Firebase ref = new Firebase("https://test.firebaseio.com/test");
        Query query = ref.orderByChild("longitude");

        //get the data from the DB
        query.addListenerForSingleValueEvent(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                //checking if the user exist
                if(dataSnapshot.exists()){
                    for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                        //get each user which has the target username
                        Location location =userSnapshot.getValue(Location.class);
                            arrayList.add(location);
                        //if the password is true , the data will be storaged in the sharedPreferences file and a Home activity will be launched
                    }
                }
                else{
                    System.out.println("not found");
                }
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {
                  System.out.println("problem ");

            }
        });
    }

    @Override
    protected Object doInBackground(Object[] params) {
        connect();
        return null;
    }

    @Override
    protected void onPostExecute(Object o) {
        super.onPostExecute(o);

        System.out.println("the firs long is"+arrayList.get(0).getLongitude());

    }
}

【问题讨论】:

  • 你的全局变量在哪里
  • arrayList 是我的全局变量
  • 是的...onPostExecute 不会等到您 arrayList 有项目。这就是为什么它是空的。
  • 一般onpostexecute是在onbackground方法执行完之后才执行的,所以必须等待
  • 不,从您的代码来看,它不会等待 ValueEventListener 方法。在完成附加 ValueEventListener 后直接调用 onPostExecute。 firebase 数据库也可以异步工作。

标签: android firebase firebase-realtime-database


【解决方案1】:

欢迎使用异步编程,它把你一直认为是真的一切都搞砸了。 :-)

Firebase 在后台自动检索/同步数据库。这项工作发生在一个单独的线程上,所以你不需要AsyncTask。但不幸的是,这也意味着你不能等待数据。

我通常建议您将代码从“先做 A,再做 B”改写为“只要我们得到 A,就用它做 B”。

在您的情况下,您想要获取数据,然后打印第一项的经度。重构即:每当收到数据时,打印第一项的经度。

Query query = ref.orderByChild("longitude");

query.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()){
            for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                Location location =userSnapshot.getValue(Location.class);
                arrayList.add(location);
            }
            System.out.println("the first long is"+arrayList.get(0).getLongitude());                }
        else{
            System.out.println("not found");
        }
    }

    @Override
    public void onCancelled(FirebaseError firebaseError) {
          System.out.println("problem ");
    }
});

这里有几点需要注意:

  1. 如果您只对第一项感兴趣,可以将查询限制为一项:query = ref.orderByChild("longitude").limitToFirst(1)。这将检索更少的数据。

  2. 我建议使用addValueEventListener() 而不是addListenerForSingleValueEvent()。前者将继续同步数据。这意味着,如果您在列表中插入/更改项目的经度,您的代码将自动重新触发并打印(可能)新的第一项。

【讨论】:

  • 我的问题是,如果我这样做,我无法从 ondatachange 方法中调用数据。arraylist.add .. 我收到一个错误,就像 ondatachange 不知道它的属性的 asynctask
  • 使用PositionateMarkerTask.this.arraylist。更好的是:摆脱异步任务,它会像MyActivity.this.arraylist
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
相关资源
最近更新 更多