Firebase数据存入ArrayList后外部为空,抛IndexOutOfBoundsException求助
解决Firebase异步加载导致ArrayList外部为空的问题
这个问题我太熟了!本质是Firebase数据库操作的异步特性在搞鬼,我来给你拆解清楚:
问题根源
Firebase的addListenerForSingleValueEvent是异步执行的——你调用get_spinner_info后,代码会立刻往下走执行Log.d,但此时onDataChange方法还没被触发(因为数据库请求还在网络传输中),所以nameList还是初始的空集合,自然会抛出IndexOutOfBoundsException。
简单说:你的Log代码跑在了数据加载完成之前。
解决方案:用回调接口处理异步结果
我们需要把依赖nameList的逻辑,放到数据加载完成的回调里执行,最常用的方式是自定义一个回调接口:
1. 先定义回调接口
在my_Item类里添加一个回调接口,用来通知数据加载完成:
public interface OnDataLoadedListener { void onDataLoaded(ArrayList<String> nameList); }
2. 修改get_spinner_info方法,加入回调参数
让方法在数据加载完成后,通过回调把结果传出去:
public void get_spinner_info(String brand, String item, String prod_key, final OnDataLoadedListener listener){ datebaseReference.child(brand).child(item).child(prod_key).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { ArrayList<String> tempList = new ArrayList<>(); for (DataSnapshot ds : dataSnapshot.child("myValue").getChildren()) { String prod_name = ds.getValue().toString(); tempList.add(prod_name); } // 数据加载完成,通过回调通知外部 listener.onDataLoaded(tempList); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { // 可以在这里处理错误,比如回调空列表或者错误信息 listener.onDataLoaded(new ArrayList<>()); } }); }
3. 修改callFunction方法,通过回调获取数据
现在不再直接访问nameList,而是等待回调通知后再处理数据:
public void callFunction(final String brand, final String item, final String product_name, final String product_key, final int product_Num) { get_spinner_info(brand, item, product_key, new OnDataLoadedListener() { @Override public void onDataLoaded(ArrayList<String> loadedNameList) { // 这里数据已经加载完成,可以安全使用了 if (!loadedNameList.isEmpty()) { Log.d("Spinner namelist : ", loadedNameList.get(0)); // 你需要用nameList做的其他操作,都放在这里 } else { Log.d("Spinner namelist : ", "列表为空"); } } }); }
另一种简化方案:把逻辑直接放到onDataChange里
如果你的业务逻辑不复杂,也可以直接把需要用到nameList的代码写到onDataChange方法内部,这样就不用额外定义回调了:
public void get_spinner_info(String brand, String item, String prod_key){ datebaseReference.child(brand).child(item).child(prod_key).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { for (DataSnapshot ds : dataSnapshot.child("myValue").getChildren()) { String prod_name = ds.getValue().toString(); nameList.add(prod_name); } // 在这里直接处理nameList,比如打印或者绑定Spinner if (!nameList.isEmpty()) { Log.d("Spinner namelist : ", nameList.get(0)); // 其他操作... } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); }
这样修改后,就能保证你在使用nameList的时候,数据已经从Firebase加载完成了。
内容的提问来源于stack exchange,提问作者yjyjy131
相关产品推荐
相关产品推荐

