使用SharedPreferences保存关卡内Show Reply功能点击次数问题
问题:购买去广告后每关卡「显示答案」功能次数限制重启后失效
需求:用户购买「Remove Ads」后,每关卡最多可使用2次「Show Reply」(显示答案)功能,且应用重启后该限制依然生效。
现状:目前仅能在单关卡内实现点击2次后禁用按钮,但退出关卡或重启应用后,点击次数会重置,可再次使用2次。
尝试方案:用SharedPreferences保存点击次数,但未正确加载数据,导致重启后数据丢失。
问题根源
- 初始化阶段未从SharedPreferences读取已保存的点击次数,
clicks默认初始化为0,导致重启后计数丢失。 - 保存点击次数时使用了通用的
clicks键,没有关联关卡标识,无法实现不同关卡的独立次数限制。 - 完成关卡时仅重置了内存中的
clicks变量,未同步更新SharedPreferences中的数据,下次进入该关卡会读取旧计数。 - 混用了两种SharedPreferences实例(默认和自定义),导致数据存储在不同文件中,读取不到之前保存的值。
修复步骤
1. 统一SharedPreferences实例
全程使用PreferenceManager.getDefaultSharedPreferences,避免数据存储位置不一致。
2. 初始化时加载对应关卡的点击次数
在onCreate中,根据当前关卡的code和branch作为key的一部分,读取保存的点击次数,并同步按钮状态:
// 读取当前关卡的点击次数,key包含关卡标识,确保每关卡独立 clicks = preferences.getInt("clicks_" + code + "_" + branch, 0); String purchasedItem = preferences.getString("purchased", null); // 如果已用满2次,直接禁用按钮 if (purchasedItem != null && clicks >= 2) { revealButton.setEnabled(false); }
3. 点击时同步保存关卡专属计数
在R.id.reveal的点击事件中,每次点击后都将计数保存到SharedPreferences,且使用关卡专属key:
if (purchasedItem != null) { // 保存当前点击次数 editor.putInt("clicks_" + code + "_" + branch, clicks); editor.apply(); if (clicks >= 2) { revealButton.setEnabled(false); Toast.makeText(this, getString(R.string.purchased_warning), Toast.LENGTH_LONG).show(); } else { // 执行显示答案的逻辑 // ... 原有显示答案代码保持不变 } }
4. 完成关卡时同步重置SharedPreferences计数
在Finish_Level_Dialog中,不仅重置内存中的clicks,还要同步更新SharedPreferences:
public void Finish_Level_Dialog() { editor.putString("done_" + code + "_" + branch, "yes"); // 重置当前关卡的点击次数 editor.putInt("clicks_" + code + "_" + branch, 0); editor.apply(); clicks = 0; }
5. 移除错误的全局重置代码
删除代码中独立于方法外的clicks = 0;语句,避免初始化时被意外重置。
修改后的关键代码片段
public class MainActivity extends Activity implements View.OnClickListener { SharedPreferences preferences; Button revealButton, askButton, doneButton; SharedPreferences.Editor editor; private int clicks; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); preferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this); editor = preferences.edit(); CurrentQuestion = preferences.getInt("CurrentQuestion" + code, 0); currentLevelQuestion = preferences.getInt("currentLevelQuestion" + code + "_" + branch, 1); // ... 广告、视图初始化等原有代码保持不变 // 加载当前关卡的点击次数并初始化按钮状态 String purchasedItem = preferences.getString("purchased", null); clicks = preferences.getInt("clicks_" + code + "_" + branch, 0); if (purchasedItem != null && clicks >= 2) { revealButton.setEnabled(false); } retrieveQuestionTile(); retrieveData(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.reveal: clicks++; Log.e("Click+1", Integer.toString(clicks)); Log.e("Test", "Click test break"); if (isRunning == true) { countDownTimer.cancel(); if (tickPlayer != null && tickPlayer.isPlaying()) { tickPlayer.stop(); } } String purchasedItem = preferences.getString("purchased", null); if (purchasedItem != null) { // 保存当前点击次数到SharedPreferences editor.putInt("clicks_" + code + "_" + branch, clicks); editor.apply(); if (clicks >= 2) { revealButton.setEnabled(false); Toast.makeText(this, getString(R.string.purchased_warning), Toast.LENGTH_LONG).show(); } else { // 执行显示答案逻辑 currentLetter = 0; for (int i = 0; i < answer.length; i++) { String Letter = String.valueOf(answer[i]); char compare = Letter.charAt(0); user_submit_answer[currentLetter] = compare; if (currentLetter + 1 < answer.length) { currentLetter = currentLetter + 1; } // 更新UI recyclerAnswersAdapter = new RecyclerAnswersAdapter(user_submit_answer, this); answerGridview.setAdapter(recyclerAnswersAdapter); recyclerAnswersAdapter.notifyDataSetChanged(); } } } else { Reveal_Answer_Dialog(); } break; // ... 其他case保持不变 } } public void Finish_Level_Dialog() { editor.putString("done_" + code + "_" + branch, "yes"); // 重置当前关卡的点击次数 editor.putInt("clicks_" + code + "_" + branch, 0); editor.apply(); clicks = 0; } }
内容的提问来源于stack exchange,提问作者Twitch Arşivim
相关产品推荐
相关产品推荐

