我在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();
否则我无法吸引任何财产。
任何想法我在做什么错。
答案 0 :(得分:3)
首先,我假设您的意思是int size = GetListMap("2019-06-24").size();
(末尾的大小)。
第二,您正在为返回的值分配一个列表,此刻它是一个空列表。然后,您附加一个等待事件(数据更改)的侦听器,如果发生此事件,则只有这样,它才会向列表中添加元素。
基本上,除非发生数据更改事件,否则列表始终为空。您需要触发一个事件,然后检查列表,它应该更改其大小。
答案 1 :(得分:3)
由于监听器的异步特性,您要在Elements集合实际上从Firebase数据库获取数据之前返回。
如果要在异步代码完成后获取更新,则必须定义一个回调
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);
``
该代码将导致以下输出:
在使用Java开发时,请 camelCase 作为方法和变量
答案 2 :(得分:1)
您将在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
}
});
答案 3 :(得分:0)
首先,您的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();
}