Firebase / Android:将检索到的值从Firebase添加到arraylist返回空指针异常 [英] Firebase/Android: Adding retrieved values from Firebase to arraylist returns null pointer exception

查看:166
本文介绍了Firebase / Android:将检索到的值从Firebase添加到arraylist返回空指针异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试将检索到的Firebase数据库中的值添加到Arraylist中,并从那里添加到String数组中。我的检索方法工作正常。我可以把所有的值打印在烤面包上。但显然它不会被添加到数组列表中。
$ b

这是我的代码,用于在片段类的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();


$ b @Override
public void onChildChanged(DataSnapshot dataSnapshot,String s){

}

@Override
公共无效onChildRemoved(DataSnapshot dataSnapshot){

}
$ b $ @覆盖
public void onChildMoved(DataSnapshot dataSnapshot,String s){

}

@Override
public void onCancelled(DatabaseError databaseError){
$ b}
});

这就是我试图在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 ++; (品牌[i] .compareTo(品牌)== 0){
f($ i

) = 1;打破;




$ b $ p
$ b这是我的数据库,但是我可以在Toast中打印出所有检索的值,没有任何问题。


从我们共享的代码中很难确定,因为我怀疑您可能会被所有数据异步加载的事实所困扰。或者,您可能根本没有权限读取数据。我将给出一个答案。



数据异步加载



最容易理解这种行为您可以在代码的最小片段中添加一些日志语句:
$ b

  System.out.println(附加侦听器之前) ; 
q.addChildEventListener(new ChildEventListener(){
public void onChildAdded(DataSnapshot dataSnapshot,String s){
System.out.println(inChildAdded);
}
public void onChildChanged(DataSnapshot dataSnapshot,String s){} $ b $ public void onChildRemoved(DataSnapshot dataSnapshot){} $ b $ public void onChildMoved(DataSnapshot dataSnapshot,String s){}
public void onCancelled(DatabaseError databaseError){}
});
System.out.println(附加监听器之后);

这段代码的输出是:

< blockquote>

在附加监听器之前

在附加监听器之后

在onChildAdded次数)

这可能不是您预期的输出顺序。这是因为Firebase(与大多数云API一样)加载数据从数据库中异步地执行:不是等待数据返回,而是继续在主线程中运行代码,然后在数据返回时调用 ChildEventListener.onChildAdded 可用。

无法等待Android上的数据。如果你这样做,你的用户会得到应用程序没有响应对话框,你的应用程序将被杀死。

因此,处理异步这个API的本质是把需要有新数据的代码放到 onChildAdded()回调函数中(也可能在其他回调函数中) ($ new $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' allBrands.add((dataSnapshot.getValue(Brand.class))。getBrandName());
System.out.println(allBrands.length);
}



您需要读取数据的权限



您需要权限才能读取如果您没有权限,Firebase会立即取消侦听器,您需要在您的代码中处理这种情况,否则您永远不会知道该信息。

  public void onCanc elled(DatabaseError databaseError){
throw databaseError.toException();
}


I'm trying the add the retrieved values from Firebase database to an Arraylist and from there to a String array. My retrieval method works fine. I can have all the values printed out in a toast. But apparently it doesn't get added to the arraylist.

Here's my code for retrieval in onActivityCreated() of fragment class.

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) {

            }
        });

And this is where I'm trying to use the arrayList in OnActivityResult() method of the Fragment class but the iterator loop is not executed I believe. The toast is not seen. I'm getting a null pointer exception when I try to work with the array. I assume the values do not get copied to the brands array.

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

Here's my database in case that helps. But I can print out all the retrieved values in a Toast with no problem.

解决方案

It's hard to be certain from the code you shared, by I suspect you may be bitten by the fact that all data is loaded from Firebase asynchronously. Alternatively you may simply not have permission to read the data. I'll give an answer for both.

Data is loaded asynchronously

It's easiest to understand this behavior when you add a few log statements to a minimal snippet of your code:

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");

The output of this snippet will be:

Before attaching listener

After attaching listener

In onChildAdded (likely multiple times)

This is probably not the order you expected the output in. This is because Firebase (like most cloud APIs) loads the data from the database asynchronously: instead of waiting for the data to return, it continues to run the code in the main thread and then calls back into your ChildEventListener.onChildAdded when the data is available.

There is no way to wait for the data on Android. If you'd do so, your users would get the daunted "Application Not Responding" dialog and your app would be killed.

So the only way to deal with the asynchronous nature of this API is to put the code that needs to have the new data into the onChildAdded() callback (and likely into the other callbacks too at some point):

q.addChildEventListener(new ChildEventListener() {
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        allBrands.add((dataSnapshot.getValue(Brand.class)).getBrandName());  
        System.out.println(allBrands.length); 
    }

You need permission to read the data

You need permission to read the data from a location. If you don't have permission, Firebase will immediately cancel the listener. You need to handle this condition in your code, otherwise you'll never know.

public void onCancelled(DatabaseError databaseError) {
    throw databaseError.toException();
}

这篇关于Firebase / Android:将检索到的值从Firebase添加到arraylist返回空指针异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆