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

时间:2016-11-15 05:09:52

标签: java android arraylist firebase firebase-realtime-database

我正在尝试将检索到的值从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中打印出所有检索到的值,没有任何问题。

Database

2 个答案:

答案 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;
  }