数组返回零,需使用多维数组但不知用法,附Firebase数据获取代码求助
你遇到的这个问题,大概率是Firebase数据库操作的异步特性导致的。addChildEventListener里的onChildAdded方法是在数据从Firebase服务器获取完成后才会回调执行的,而你如果在调用dbQuery.addChildEventListener(...)之后立刻去访问weather数组的话,此时回调还没触发,数组自然是空的。
举个反例,如果你原来的代码是这样的:
List<model> weather = new ArrayList<model>(); Query dbQuery = FirebaseDatabase.getInstance().getReference().child("NeuralNetwork"); dbQuery.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { model m = dataSnapshot.getValue(model.class); weather.add(m); // 这里才会往数组里加数据 } // 其他重写方法省略... }); // 这里立刻打印size,肯定是0,因为onChildAdded还没执行 Log.d("TAG", weather.size() + "");
解决办法很直接:所有需要使用weather数组的逻辑,都要放在onChildAdded回调里面(或者回调触发之后)。比如你要处理数据、更新UI,都得在回调里做:
@Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { model m = dataSnapshot.getValue(model.class); weather.add(m); // 在这里处理数据,比如转换成多维数组,或者更新UI processWeatherData(weather); updateWeatherUI(weather); }
如果你的业务逻辑需要在所有子节点都加载完成后再处理,可以改用addListenerForSingleValueEvent的onDataChange方法,它会一次性获取所有数据:
dbQuery.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) { model m = childSnapshot.getValue(model.class); weather.add(m); } // 所有数据都加载完了,这里可以放心使用weather数组 convertToMultiDimensionalArray(weather); } @Override public void onCancelled(DatabaseError databaseError) { // 记得处理数据库请求失败的情况 Log.e("TAG", "数据获取失败:" + databaseError.getMessage()); } });
另外还要注意:你的model类字段要和Firebase数据库里的键完全匹配(大小写敏感),否则getValue(model.class)会解析失败,也会导致数组为空。
结合你的需求,你需要把每个model里的previous、humidity、temperature、wind这些数值存到多维数组里。多维数组可以理解为“数组的数组”,比如int[][]类型,每个子数组对应一个model的四个参数。
方法1:使用原生二维数组(固定长度)
如果能提前知道数据总条数(可以通过dataSnapshot.getChildrenCount()获取),可以直接初始化固定长度的二维数组:
@Override public void onDataChange(DataSnapshot dataSnapshot) { int dataCount = (int) dataSnapshot.getChildrenCount(); // 每行存4个参数:previous、humidity、temperature、wind int[][] weatherMultiArray = new int[dataCount][4]; int currentIndex = 0; for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) { model m = childSnapshot.getValue(model.class); weatherMultiArray[currentIndex][0] = m.getPrevious(); weatherMultiArray[currentIndex][1] = m.getHumidity(); weatherMultiArray[currentIndex][2] = m.getTemperature(); weatherMultiArray[currentIndex][3] = m.getWind(); currentIndex++; } // 现在就可以使用这个多维数组了,比如打印第一组数据 Log.d("TAG", "第一组数据:" + weatherMultiArray[0][0] + ", " + weatherMultiArray[0][1] + ", " + weatherMultiArray[0][2] + ", " + weatherMultiArray[0][3]); }
方法2:使用ArrayList<int[]>(动态长度)
如果不确定数据条数,或者需要动态添加数据,用ArrayList<int[]>会更灵活,不需要提前指定长度:
// 先在回调外声明这个列表 List<int[]> weatherMultiList = new ArrayList<>(); @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { model m = dataSnapshot.getValue(model.class); int[] singleWeatherData = new int[4]; singleWeatherData[0] = m.getPrevious(); singleWeatherData[1] = m.getHumidity(); singleWeatherData[2] = m.getTemperature(); singleWeatherData[3] = m.getWind(); weatherMultiList.add(singleWeatherData); // 每次添加后都可以使用这个列表,比如打印当前数据条数 Log.d("TAG", "当前累计数据条数:" + weatherMultiList.size()); }
内容的提问来源于stack exchange,提问作者Jane

