【问题标题】:How can I get data out of onDataChange method?如何从 onDataChange 方法中获取数据?
【发布时间】:2019-03-22 00:12:54
【问题描述】:

情况:我想将我的函数参数中的 url 与从我的 firebase 实时数据库中检索到的 url 进行比较。检索有效,但是,我不知道如何从 if-else 语句中的字符串比较中获取布尔值,其中出现错误:“无法将值赋给最终变量 'bool'”。

compare() 代码

private boolean compare(String url) {
    mDatabaseReference = mFirebaseDatabase.getReference("Executive Branch");
    final String newUrl = url;
    final boolean bool = false;

    mDatabaseReference.limitToFirst(1).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.getChildrenCount() > 0) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    ExecutiveOrder executiveOrder = snapshot.getValue(ExecutiveOrder.class);
                    if (executiveOrder.getUrl().equals(newUrl)) {
                        bool = true;
                    } else {
                        bool = false;
                    }
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e("Executive Order", "The read failed: " + databaseError.getDetails());
        }
    });

    return bool;
}

【问题讨论】:

    标签: android firebase firebase-realtime-database


    【解决方案1】:

    您不能为最终变量分配新值。

    如果你要访问内部类中的外部类变量,它们必须声明为 final。

    一种简单但不优雅的方法是声明一个大小为 1 的布尔数组。

    mDatabaseReference = mFirebaseDatabase.getReference("Executive Branch");
    final String newUrl = url;
    final boolean[] bool = new boolean[1];   //boolean array of size 1
    
    mDatabaseReference.limitToFirst(1).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.getChildrenCount() > 0) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    ExecutiveOrder executiveOrder = snapshot.getValue(ExecutiveOrder.class);
                    if (executiveOrder.getUrl().equals(newUrl)) {
                        bool[0] = true;   //access the bool value like this
                    } else {
                        bool[0] = false;
                    }
                }
            }
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e("Executive Order", "The read failed: " + databaseError.getDetails());
        }
    });
    

    顺便说一句,你犯了一个大错误。你的代码会一直返回 false。

    Firebase 数据库方法是异步的,这意味着它们在单独的线程中执行,因此我们无法阻止它们何时从数据库中检索数据。这取决于您的互联网速度。

    所以你必须在onDataChange 方法中调用适当的方法。示例...

    private boolean compare(String url) {
        mDatabaseReference = mFirebaseDatabase.getReference("Executive Branch");
        final String newUrl = url;
    
        mDatabaseReference.limitToFirst(1).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if (dataSnapshot.getChildrenCount() > 0) {
                    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                        ExecutiveOrder executiveOrder = snapshot.getValue(ExecutiveOrder.class);
                        boolean bool = executiveOrder.getUrl().equals(newUrl);
                        doSomething(bool); //This method will handle the logic
                    }
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.e("Executive Order", "The read failed: " + databaseError.getDetails());
            }
        });
    }
    

    【讨论】:

      【解决方案2】:

      错误告诉你问题出在哪里。您正在尝试将值分配给最终变量。尝试直接返回 true 或 false。但请注意,firebase 调用是异步的,这意味着它可能会在您的方法底部返回默认值。

      private boolean compare(String url) {
          mDatabaseReference = mFirebaseDatabase.getReference("Executive Branch");
          final String newUrl = url;
          final boolean bool;
      
          mDatabaseReference.limitToFirst(1).addValueEventListener(new ValueEventListener() {
              @Override
              public void onDataChange(DataSnapshot dataSnapshot) {
                  if (dataSnapshot.getChildrenCount() > 0) {
                      for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                          ExecutiveOrder executiveOrder = snapshot.getValue(ExecutiveOrder.class);
                          if (executiveOrder.getUrl().equals(newUrl)) {
                              bool = true;
                          } else {
                              bool = false;
                          }
                      }
                  }
              }
      
              @Override
              public void onCancelled(DatabaseError databaseError) {
                  Log.e("Executive Order", "The read failed: " + databaseError.getDetails());
              }
          });
      
          if(bool!=null)        < Add a condition to check if bool is null or not
          return bool;
          else return false;
      }
      

      【讨论】:

      • 虽然无法从 void 结果类型的方法返回真或假
      • 你知道任何其他可能的方法来返回真或假吗?
      • 我改了答案,现在应该没问题了。但我建议您提前进行 firebase 检索,这样您就无需阻塞或等待结果。
      【解决方案3】:

      在您的类中将变量 bool 设为全局变量并删除 final 关键字,以便您可以从方法内的任何位置读取和写入值。

      【讨论】:

        【解决方案4】:

        如果你想使用 onDataChange 方法之外的变量,请在 onDataChange 方法之外的方法中编写你想要使用该变量执行的所有过程。这个方法应该有一个字符串作为参数(因为我们主要从 firebase 接收值作为字符串)。现在,在 onDataChange 方法中调用该方法,并将 onDataChange 的变量作为参数传递给该方法。

        例如:

        public void onDataChange(DataSnapshot dataSnapshot) {
           String firebaseVariable=dataSnapshot.getValue().toString();
           methodToProcess(firebaseVariable);
        }
        
        methodToProcess(String firebaseVariable){
        //Your processing here
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-02-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-04
          • 1970-01-01
          相关资源
          最近更新 更多