Android开发:Intent传值始终为空及SharedPreferences读取异常的跳转问题
嘿,我来帮你捋清楚这个问题,大概率是SharedPreferences的使用细节没处理好,或者跳转逻辑的时机不对~咱们一步步来排查和解决:
先搞懂核心问题:为什么SharedPreferences读不到值?
你遇到的取不到值/拿到默认值,通常是这几个坑:
- 保存时没提交:只调用了
edit().putXXX(),但没加apply()或commit(),导致值根本没写入本地 - 文件名不统一:存和读用了不同的SharedPreferences文件名,相当于两个不同的存储文件,自然读不到
- 读取时机不对:如果FirstLogActivity一直在栈里没销毁,只在
onCreate里读一次,回到FirstLog时不会重新执行onCreate,所以拿不到新存的值
解决方案:标准化SharedPreferences+优化跳转逻辑
1. 写一个统一的SharedPreferences工具类(避免重复踩坑)
把SharedPreferences的操作封装成单例工具类,确保全应用用的是同一个存储文件:
public class PrefUtils { // 统一存储文件名,别随便改 private static final String PREF_NAME = "AppFlowPrefs"; private static SharedPreferences sPrefs; private static SharedPreferences.Editor sEditor; // 私有构造,不让外部实例化 private PrefUtils() {} // 在Application初始化时调用一次 public static void init(Context context) { if (sPrefs == null) { sPrefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); sEditor = sPrefs.edit(); } } // 保存"是否完成过完整流程"的标记 public static void setFlowCompleted(boolean isCompleted) { sEditor.putBoolean("has_completed_flow", isCompleted); sEditor.apply(); // 异步提交,比commit更高效;如果要确保同步成功用commit() } // 获取标记,默认值是false(还没完成过流程) public static boolean isFlowCompleted() { return sPrefs.getBoolean("has_completed_flow", false); } }
然后在自定义Application里初始化这个工具类(记得在Manifest里注册):
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); PrefUtils.init(this); } }
Manifest里的注册:
<application android:name=".MyApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" ...> <!-- 你的Activity注册 --> </application>
2. 在MapsActivity中保存流程完成标记
当用户从MapsActivity返回FirstLog时,把标记存进去:
// 比如在返回按钮的点击事件,或者onBackPressed里: @Override public void onBackPressed() { // 标记已经走完了一次完整流程 PrefUtils.setFlowCompleted(true); super.onBackPressed(); } // 如果是用Intent主动跳转回FirstLog,就在跳转前保存: Intent backToFirstLog = new Intent(this, FirstLogActivity.class); PrefUtils.setFlowCompleted(true); startActivity(backToFirstLog); finish(); // 这里finish MapsActivity没问题
3. 在FirstLogActivity中判断标记并跳转
重点:要在onResume里判断,而不是只在onCreate!因为如果FirstLog一直在栈里,回到它时不会重新走onCreate,但会走onResume:
@Override protected void onResume() { super.onResume(); // 检查是否已经完成过完整流程 if (PrefUtils.isFlowCompleted()) { // 直接跳转到MapsActivity Intent toMaps = new Intent(this, MapsActivity.class); // 可选:如果想清理栈里的其他Activity,加这两个flag toMaps.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(toMaps); finish(); // 可选:如果不想保留FirstLog在栈里,就finish掉 return; } // 如果没完成过流程,就正常走跳转Explanation的逻辑 // 比如你的启动按钮点击事件: btnStart.setOnClickListener(v -> { Intent toExplanation = new Intent(this, ExplanationActivity.class); startActivity(toExplanation); }); }
额外排查点(如果你之前的代码还有问题)
- 检查你之前的SharedPreferences是否用了相同的文件名
- 确认保存时有没有调用
apply()/commit()——这是最容易忘的! - 看看FirstLogActivity的启动模式是不是
singleTop/singleTask,如果是,一定要在onResume里读取标记
内容的提问来源于stack exchange,提问作者shahar481
相关产品推荐
相关产品推荐

