从Firebase取数据存SharedPreferences后读取为null的问题排查
问题分析与解决方案
这个问题我之前也碰到过,核心原因就是Firebase的异步回调特性在搞鬼,咱们一步步拆解清楚:
为什么Toast能显示但另一个Activity读不到值?
你在onCreate()里调用了getLocDbs(),但Firebase的addListenerForSingleValueEvent是异步执行的——也就是说,onDataChange()方法里的代码不会立刻运行,而是要等Firebase从服务器拿到数据后才会触发。
- 你看到的Toast能正常显示,是因为Toast的代码写在
onDataChange()里面,此时数据已经成功获取,并且SharedPreferences也完成了写入; - 但如果在
getLocDbs()调用后直接跳转到另一个Activity,这个跳转动作会在Firebase回调执行前就完成——此时另一个Activity去读取SharedPreferences时,数据还没被写入,自然得到null。
具体解决方案
1. 确保数据写入完成后再执行跳转操作
把跳转到另一个Activity的逻辑,移到onDataChange()方法的末尾,这样就能保证只有当数据成功写入SharedPreferences后,才会进入下一个页面:
public void getLocDbs() { firebaseRef.child("rpi_lox").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { // 1. 获取Firebase返回的数据 String locData = snapshot.getValue(String.class); // 2. 写入SharedPreferences SharedPreferences prefs = getSharedPreferences("YourPrefsName", MODE_PRIVATE); prefs.edit() .putString("saved_loc_dbs", locData) .apply(); // apply是异步写入但内存会立刻更新,也可以用commit()同步写入 // 3. 显示Toast(此时数据已就绪) Toast.makeText(CurrentActivity.this, locData, Toast.LENGTH_SHORT).show(); // 4. 数据写入完成后,再跳转到目标Activity Intent intent = new Intent(CurrentActivity.this, TargetActivity.class); startActivity(intent); } @Override public void onCancelled(@NonNull DatabaseError error) { // 别忘了处理获取数据失败的情况 Toast.makeText(CurrentActivity.this, "数据获取失败", Toast.LENGTH_SHORT).show(); } }); }
2. 检查SharedPreferences的读取逻辑是否正确
在另一个Activity里读取时,要确保使用相同的SharedPreferences名称和键名,比如:
// 目标Activity的读取代码 SharedPreferences prefs = getSharedPreferences("YourPrefsName", MODE_PRIVATE); String savedData = prefs.getString("saved_loc_dbs", null); // 这里可以加日志验证 if (savedData != null) { Log.d("SharedPrefs", "读取到的数据:" + savedData); } else { Log.d("SharedPrefs", "读取到null,可能数据还没写入"); }
额外注意点
- 不用再套AsyncTask了,Firebase本身已经是异步的,多此一举反而可能引入新的线程问题;
- 如果你的业务逻辑不能在回调里直接跳转(比如需要等待多个异步操作完成),可以自定义一个回调接口,用来通知数据准备完毕,再执行后续操作。
内容的提问来源于stack exchange,提问作者jerry fa
相关产品推荐
相关产品推荐

