Firebase / Android:将检索到的值从Firebase添加到arraylist会返回空指针exception

我正在尝试将检索到的值从Firebase数据库添加到Arraylist并从那里添加到String数组。 我的检索方法工作正常。 我可以把所有的价值都打印出来。 但显然它并没有被添加到arraylist。

这是我在片段类的onActivityCreated()中检索的代码。

ArrayList 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但我相信迭代器循环没有被执行的地方。 没看到吐司。 当我尝试使用数组时,我得到一个空指针exception。 我假设这些值不会被复制到brands数组中。

 count=allBrands.size(); String[] brands=new String[count]; Iterator 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中打印出所有检索到的值,没有任何问题。

数据库

很难从您共享的代码中确定,我怀疑您可能会被所有数据从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()回调中(并且在某些时候也可能放入其他回调):

 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(); } 

试试这个(我写这个也是为了我自己的未来参考..)

正如您所看到的,我们在结束之前实施了重新打包。 可能有更好的方法来做到这一点。 但是,没有记录。 此外,所有这些事件列表器都应该自动添加并由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 mGamesPlaying = new ArrayList<>(); public ArrayList 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; }