Android应用SharedPreferences与内购报错:空指针异常解决求助
解决FirstActivity的NullPointerException问题
这个崩溃的核心原因很明确:你手动实例化了MyketActivity,但Activity是Android系统管理的组件,不能通过new关键字直接创建实例。你这样做的话,系统不会调用MyketActivity的onCreate方法,导致里面的editor_logginTimer变量始终是null,调用getLogginTime(1)时自然会触发空指针异常。
下面是具体的修复方案,同时优化你的代码结构:
第一步:把SharedPreferences操作抽成独立工具类
Activity不应该承担数据存储的工具职责,我们把SharedPreferences的读写逻辑抽成一个通用工具类,这样所有页面都能安全调用:
public class SharedPrefsUtils { // 定义SharedPreferences文件名和存储键名 private static final String PREF_FILE_NAME = "login_times"; private static final String KEY_LOGIN_COUNT = "times"; // 保存登录次数 public static void saveLoginCount(Context context, int count) { SharedPreferences prefs = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putInt(KEY_LOGIN_COUNT, count); editor.apply(); // 用apply()替代commit(),异步提交更高效 } // 获取登录次数,默认返回0 public static int getLoginCount(Context context) { SharedPreferences prefs = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE); return prefs.getInt(KEY_LOGIN_COUNT, 0); } }
第二步:修改FirstActivity的代码
在FirstActivity里直接调用工具类保存次数,不需要依赖MyketActivity:
public class FirstActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.first_activity); // 首次启动,保存次数为1 SharedPrefsUtils.saveLoginCount(this, 1); // 跳转到主页面,结束当前页面避免返回 startActivity(new Intent(this, MainActivity.class)); finish(); } }
第三步:修改MainActivity的代码
后续启动进入MainActivity时,更新次数并检查:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); // 获取当前次数,更新为2(或者如果是每次启动递增,就用currentCount +1) int currentCount = SharedPrefsUtils.getLoginCount(this); SharedPrefsUtils.saveLoginCount(this, 2); // 按你的需求设置为2 // 检查次数,触发内购逻辑 checkLoginCountAndHandlePurchase(); } private void checkLoginCountAndHandlePurchase() { int loginCount = SharedPrefsUtils.getLoginCount(this); if (loginCount >= 2) { // 跳转到内购页面 startActivity(new Intent(this, MyketActivity.class)); } } }
第四步:优化MyketActivity的代码
MyketActivity里直接用工具类获取次数,去掉原来的静态SharedPreferences变量:
public class MyketActivity extends Activity { private BackDialog purchaseDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.myket); // 检查登录次数,处理内购逻辑 int loginCount = SharedPrefsUtils.getLoginCount(this); if (loginCount >= 2) { showPurchaseDialog(); } } private void showPurchaseDialog() { // 你的内购弹窗逻辑 } }
额外注意事项
- 永远不要手动new Activity实例:Activity的生命周期由Android系统控制,必须通过
Intent启动,否则所有依赖生命周期的初始化逻辑(比如getSharedPreferences、setContentView)都不会执行。 - 使用
apply()替代commit():commit()是同步提交到磁盘,可能阻塞主线程;apply()是异步提交,更适合UI线程操作。 - 避免内存泄漏:工具类中使用
Context时,如果是长期操作,建议传入getApplicationContext()而不是Activity实例,避免Activity被销毁后仍被引用。
内容的提问来源于stack exchange,提问作者user4568864
相关产品推荐
相关产品推荐

