You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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() {
        // 你的内购弹窗逻辑
    }
}

额外注意事项

  1. 永远不要手动new Activity实例:Activity的生命周期由Android系统控制,必须通过Intent启动,否则所有依赖生命周期的初始化逻辑(比如getSharedPreferences、setContentView)都不会执行。
  2. 使用apply()替代commit():commit()是同步提交到磁盘,可能阻塞主线程;apply()是异步提交,更适合UI线程操作。
  3. 避免内存泄漏:工具类中使用Context时,如果是长期操作,建议传入getApplicationContext()而不是Activity实例,避免Activity被销毁后仍被引用。

内容的提问来源于stack exchange,提问作者user4568864

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:32:13