我正在尝试将检索到的值从Firebase数据库添加到Arraylist并从那里添加到String数组。我的检索方法工作正常。我可以把所有的价值都打印出来。但显然它并没有被添加到arraylist。
这是我在片段类的onActivityCreated()中检索的代码。
ArrayList<String> allBrands = new ArrayList<>();
brandRef=FirebaseDatabase.getInstance().getReferenceFromUrl("https://stockmanager-142503.firebaseio.com/Brands");
q=brandRef.orderByChild("brandName");
q.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
allBrands.add((dataSnapshot.getValue(Brand.class)).getBrandName());
Toast.makeText(getActivity(),(dataSnapshot.getValue(Brand.class)).getBrandName(), Toast.LENGTH_SHORT).show();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
这就是我在Fragment类的OnActivityResult()方法中尝试使用arrayList但我相信迭代器循环没有被执行的地方。没看到吐司。当我尝试使用数组时,我得到一个空指针异常。我假设这些值不会被复制到品牌阵列。
count=allBrands.size();
String[] brands=new String[count];
Iterator<String> itemIterator = allBrands.iterator();
if(itemIterator.hasNext()){
//brands[i] = itemIterator.next();
Toast.makeText(getActivity(), itemIterator.next(), Toast.LENGTH_SHORT).show();
// i++;
}
for( i=0;i<count;i++){
if(brands[i].compareTo(Brand)==0){
f=1;break;
}
}
这是我的数据库以防万一。但我可以在Toast中打印出所有检索到的值,没有任何问题。
答案 0 :(得分:3)
很难确定您所分享的代码,我怀疑您可能会被所有数据异步加载从Firebase这一事实所困扰。或者,您可能根本没有读取数据的权限。我会给两个答案。
当您向代码的最小片段添加一些日志语句时,最容易理解这种行为:
System.out.println("Before attaching listener");
q.addChildEventListener(new ChildEventListener() {
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
System.out.println("In onChildAdded");
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) { }
public void onChildRemoved(DataSnapshot dataSnapshot) { }
public void onChildMoved(DataSnapshot dataSnapshot, String s) { }
public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After attaching listener");
此代码段的输出将为:
在附加监听器之前
附加监听器后
在onChildAdded(可能是多次)
这可能不是您期望输出的顺序。这是因为Firebase(像大多数云API一样)异步加载来自数据库的数据:它不是等待数据返回,而是继续运行代码。主线程,然后在数据可用时回调到ChildEventListener.onChildAdded
。
没有办法等待Android上的数据。如果你这样做了,你的用户就会得到被淹没的“应用程序无响应”对话框,你的应用程序就会被杀死。
因此,处理此API的异步性质的唯一方法是将需要拥有新数据的代码放入onChildAdded()
回调(并且在某些时候也可能放入其他回调):< / p>
q.addChildEventListener(new ChildEventListener() {
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
allBrands.add((dataSnapshot.getValue(Brand.class)).getBrandName());
System.out.println(allBrands.length);
}
您需要获得从某个位置读取数据的权限。如果您没有权限,Firebase将立即取消该监听器。你需要在你的代码中处理这个条件,否则你永远不会知道。
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
答案 1 :(得分:0)
试试这个(我写这个也是为了我自己的未来参考......)
正如您所看到的,我们在结束之前实施了重新打包。可能有更好的方法来做到这一点。但是,没有记录。此外,所有这些事件列表器都应该自动添加并由firebase自动释放,但是由于某些原因它们不会这样做。
/**
* @param uid User's ID
* @param Callable send as null just to implement a call to assure the callback is updapted before it's finished
* @return returns ArrayList of all Games unique identification key enlisted in a User
*/
private final ArrayList<String> mGamesPlaying = new ArrayList<>();
public ArrayList<String> mGamesPlaying(final String uid, final Callable refresh) {
final Firebase ref = FirebaseRef;
Firebase usersRef = ref.child("users").child(uid).child("playing_games");
usersRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
mGamesPlaying.clear();
for (DataSnapshot child : snapshot.getChildren()) {
Log.d(TAG, "Test Game" + child.getKey());
mGamesPlaying.add(child.getKey());
}
try {
refresh.call();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
return mGamesPlaying;
}