重启Android应用后点击按钮无法从Firebase读取用户数据报空指针
问题排查与解决方案
核心原因分析
Firebase Realtime Database的addListenerForSingleValueEvent是异步操作,调用prelevaDati()后不会立刻给全局utente对象赋值,代码会继续向下执行。
第一个按钮逻辑调用prelevaDati()后是启动ProfiloFragment,Fragment的渲染存在时间差,等Fragment需要使用utente时,异步回调已经执行完成,utente已经赋值所以不会报错。
第二个按钮逻辑在调用prelevaDati()后立刻访问utente.getScheda(),此时异步请求还未返回,utente仍为空就会抛出空指针异常。
至于回调未触发,常见原因有三种:
- 开启了Firebase离线持久化时,
addListenerForSingleValueEvent会优先返回本地缓存,本地无缓存且网络不稳定时就会出现回调不触发的情况 - 重启应用后Firebase Auth状态恢复延迟,或者
mDatabase实例初始化异常 - 数据库对应路径的读取权限配置错误
解决步骤
第一步:修改为异步回调后操作数据
先定义回调接口,所有utente相关的操作都放在异步回调返回后执行:
// 定义数据加载回调接口 public interface DatiCallback { void onDatiCaricati(Utente utente); void onErrore(DatabaseError error); } // 改造prelevaDati方法支持回调 public void prelevaDati(DatiCallback callback) { mDatabase.child("Utenti").child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { utente = snapshot.getValue(Utente.class); if (callback != null) { callback.onDatiCaricati(utente); } } @Override public void onCancelled(@NonNull DatabaseError error) { if (callback != null) { callback.onErrore(error); } } }); }
修改第二个按钮的逻辑:
case R.id.buttonScheda: if(mAuth.getCurrentUser() == null) { accessoFragment.show(getSupportFragmentManager(), accessoFragment.getTag()); return; // 未登录直接终止后续逻辑 } prelevaDati(new DatiCallback() { @Override public void onDatiCaricati(Utente utente) { if (utente != null) { toolbar.setSubtitle("SCHEDA"); child = "Scheda"; // 所有调用utente.getScheda()的逻辑都放在此处执行 } } @Override public void onErrore(DatabaseError error) { // 自行添加错误处理逻辑,比如打印日志、弹窗提示 Log.e("DB_ERROR", "数据读取失败", error.toException()); } }); break;
如果要统一避免异常,第一个按钮的逻辑也可以改成上述回调写法,适配极端网络场景。
第二步:排查回调未触发问题
- 检查Firebase Realtime Database的规则配置,确认
/Utenti路径下对应uid的节点开启了读取权限 - 重启应用后添加日志打印
mAuth.getCurrentUser().getUid(),确认Auth状态恢复正常 - 如果开启了离线持久化,可调用
FirebaseDatabase.getInstance().goOnline()强制连接服务器,或者换用addValueEventListener做持久监听
第三步:全局添加空指针防护
所有访问utente对象的位置都添加非空判断,避免异常崩溃。
内容的提问来源于stack exchange,提问作者Bryan Sanchez
相关产品推荐
相关产品推荐

