【问题标题】:Java List<Object> sizeJava 列表<对象> 大小
【发布时间】:2019-06-25 21:02:57
【问题描述】:

我在java android中有一个列表:

List<FirebaseData> GetListMap(String data){

    final List<FirebaseData> Elements = new ArrayList<>();

    FirebaseDatabase database = FirebaseDatabase.getInstance();

    mShiftReference = database.getReference("Map/Data/").child(data);

    mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            for (DataSnapshot child: dataSnapshot.getChildren()) {

                Elements.add(child.getValue(FirebaseData.class));
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            // Failed to read value
            Log.w("data", "Failed to read value.", error.toException());
        }
    });

    return Elements;
}

当我尝试提取数组的大小时,它返回 0,例如:

int size = GetListMap("2019-06-24").size();

或者我无法提取任何属性。

知道我做错了什么。

【问题讨论】:

  • GetListMap 返回 List&lt;FirebaseData&gt;,但您将其结果分配给 int。究竟发生了什么? (这看起来像是在为稍后发生更改时添加一个侦听器,但实际上并不清楚您是否已经等待更改发生。)
  • 对不起@LouisWasserman 你是对的,应该是int size = GetListMap("2019-06-24").size();

标签: java android arrays arraylist


【解决方案1】:

首先,我假设您的意思是 int size = GetListMap("2019-06-24").size();(最后的大小)。

其次,您正在为返回值分配一个列表,此时它是一个空列表。然后您附加一个等待事件(数据更改)的侦听器,如果发生这种情况,那么它才会将一个元素添加到列表中。

基本上,除非发生数据更改事件,否则您的列表将始终为空。你需要触发一个事件然后检查列表,它应该改变它的大小。

【讨论】:

  • 我刚刚做了,但不幸的是没有任何改变。无论如何,感谢您回复 +1。
【解决方案2】:

由于侦听器的异步特性,您在实际从 Firebase 数据库获取数据之前返回了 Elements 集合。

如果要在异步代码完成后获取更新,则必须定义回调

List<FirebaseData> GetListMap(String data){

final List<FirebaseData> Elements = new ArrayList<>();

FirebaseDatabase database = FirebaseDatabase.getInstance();

mShiftReference = database.getReference("Map/Data/").child(data);

mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        System.out.println("About to fill Elements");
        for (DataSnapshot child: dataSnapshot.getChildren()) {

            Elements.add(child.getValue(FirebaseData.class));
        }
        System.out.println("Elements is filled");

    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        // Failed to read value
        Log.w("data", "Failed to read value.", error.toException());
    }
});
System.out.println("Returning Elements with size: " + Elements.size());
return Elements;
}
int x = GetListMap("...").size();
System.out.println("x: +" x);

``

该代码将产生以下输出:

  1. 返回大小为 0 的元素
  2. x: 0
  3. 即将填充元素
  4. 元素已填充

顺便说一句,当您使用 Java 进行开发时,请使用 camelCase 作为您的方法和变量

【讨论】:

    【解决方案3】:

    您在 firebase 完成添加所有内容之前返回列表。你想为函数创建一个接口方法。

    在类中创建接口:

    public interface Complete{
        void taskCompleted(List<FirebaseData> list);
    }
    

    然后将其分配给您的方法(现在返回 void,因为接口将产生结果):

    public void GetListMap(String data, Complete completeListener){
    
    . . . .
    
    mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot child: dataSnapshot.getChildren()) {
                Elements.add(child.getValue(FirebaseData.class));
            }
    
            completeListener.taskComplete(Elements);
        }
    
        @Override
        public void onCancelled(@NonNull DatabaseError error) {
                completeListener.taskComplete(null);
            }
        });
    
    }
    

    使用方法:

    GetListMap("data", new Complete() {
                        @Override
                        public void taskCompleted(List<FirebaseData> list) {
                            //do what you want with the list object
                        }
                    });
    

    【讨论】:

      【解决方案4】:

      首先,您的GetListMap 方法包含firebase 数据库调用,其中当然是异步调用。意味着您正在单独的线程上获取数据。因此,此调用下方的行在 firebase 进程查询响应之前执行。所以无法从包含异步函数的方法中获取返回值。

      因此,要获得您想要的确切信息,您必须等待查询响应。

      参考下面的代码来实现你想要的。

      // Avoiding return type with this method.
      void GetListMap(String data){
      
          final List<FirebaseData> Elements = new ArrayList<>();
      
          FirebaseDatabase database = FirebaseDatabase.getInstance();
      
          mShiftReference = database.getReference("Map/Data/").child(data);
      
          mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
              @Override
              public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
      
                  for (DataSnapshot child: dataSnapshot.getChildren()) {
      
                      Elements.add(child.getValue(FirebaseData.class));
                  }
      
                  // Use below method to update data inside your views.
                  // This method will only called once firebase query return response.
                  updateUI(Elements); 
              }
      
              @Override
              public void onCancelled(@NonNull DatabaseError error) {
                  // Failed to read value
                  Log.w("data", "Failed to read value.", error.toException());
              }
          });
      
          // Now this method is void so need to return any value.
          //return Elements;
      }
      

      updateUI(...) 方法的示例。

      void updateUI(List<FirebaseData> elements) {
      
         int size = elements.size();
      
      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-01
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-04
        相关资源
        最近更新 更多