Firebase/Android:将检索到的值从 Firebase 添加到 arraylist 会返回空指针异常
Posted
技术标签:
【中文标题】Firebase/Android:将检索到的值从 Firebase 添加到 arraylist 会返回空指针异常【英文标题】:Firebase/Android: Adding retrieved values from Firebase to arraylist returns null pointer exception 【发布时间】:2017-03-28 21:35:54 【问题描述】:我正在尝试将检索到的值从 Firebase 数据库添加到 Arraylist 并从那里添加到 String 数组。我的检索方法工作正常。我可以在吐司中打印出所有值。但显然它没有被添加到数组列表中。
这是我在片段类的 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 中所有检索到的值。
【问题讨论】:
【参考方案1】:很难从您共享的代码中确定,我怀疑您可能会被所有数据都是从 Firebase 异步加载的事实所困扰。或者,您可能根本没有读取数据的权限。两者我都会给出答案。
数据是异步加载的
当您将一些日志语句添加到代码的最小 sn-p 中时,最容易理解这种行为:
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");
这个 sn-p 的输出将是:
附加监听器之前
附加监听器后
在 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();
【讨论】:
谢谢。是否可以将检索到的数据传递给 onActivityResult 方法?这样应用程序会等到检索完成,不是吗? 您可以在ChildEventListener
的方法中调用onActivityResult()
。这些方法在主线程上调用。【参考方案2】:
试试这个(我写这个也是为了将来自己参考)
如您所见,我们在结束之前实施了重新刷新。可能有更好的方法来做到这一点。但是,它没有记录。此外,所有这些事件Listners都应该自动添加并由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;
【讨论】:
以上是关于Firebase/Android:将检索到的值从 Firebase 添加到 arraylist 会返回空指针异常的主要内容,如果未能解决你的问题,请参考以下文章
将从 spring-boot 检索到的数据转换为 JSON 并在 Angular 前端获取它