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

Android/Java SharedPreferences持久化Vector Assets货币设置

问题根因

你的货币选择配置实际上已经写入了SharedPreferences,重启后重置是代码逻辑错误导致的,核心问题有4个:

  • 字符串比较逻辑完全失效:Java中==比较的是对象内存地址,不是字符串实际内容。你所有判断货币类型的分支都用==匹配固定字符串,但从SharedPreferences读取出来的字符串是独立的新对象,和代码中写的字符串常量内存地址不一致,所有判断分支都不会命中,图标设置逻辑不执行,看起来像是配置重置回了默认。
  • SharedPreferences键值冲突:你使用同一个PREF_CURRENCY_VALUE键先后存储字符串、整数类型值,后写入的int值会覆盖之前的字符串值,导致读取结果不符合预期。
  • 监听器绑定逻辑冗余:你在Spinner的onItemSelected回调里反复给保存按钮绑定点击事件,会导致多个监听器叠加,执行逻辑混乱。
  • 缺少默认值与回显逻辑:读取SharedPreferences时默认值传了空字符串,首次启动无配置时没有默认加载美元的规则;进入设置页时也没有读取已保存配置回显到Spinner上,用户看不到之前的选择。
修复方案
  1. 所有字符串内容判断全部改用equals()方法,禁止用==比较字符串
  2. 清理SharedPreferences冗余键,只存储稳定的货币ID即可,名称、图标通过ID映射获取,避免重复存储数据不一致
  3. 把保存按钮的点击监听器从Spinner选中回调中移出来,仅在onCreate中绑定一次,点击时直接获取当前Spinner选中值保存
  4. 增加设置页回显逻辑,进入页面时自动选中已保存的货币项
  5. 配置默认值,首次启动默认加载美元

修复后代码

1. 改造Currency类,统一配置常量与映射方法

package com.myproject.offlinebudgettrackerappproject;

import java.util.ArrayList;

public class Currency {
    // 统一SharedPreferences常量,避免硬编码写错键名
    public static final String PREF_NAME = "CURRENCY_SHARED";
    public static final String KEY_CURRENCY_ID = "selected_currency_id";
    public static final String DEFAULT_CURRENCY_ID = "0"; // 默认美元对应ID

    private static ArrayList<Currency> currencyArrayList = new ArrayList<>();
    private String id;
    private String currency;

    public Currency(String id, String currency) {
        this.id = id;
        this.currency = currency;
    }

    public Currency() {}

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCurrency() {
        return currency;
    }

    public void setCurrency(String currency) {
        this.currency = currency;
    }

    public static void initCurrencies() {
        // 初始化前先清空列表,避免重复进入页面时货币项重复添加
        currencyArrayList.clear();
        Currency usd = new Currency("0", "US Dollars");
        currencyArrayList.add(usd);
        Currency jpy = new Currency("1", "Japanese Yen");
        currencyArrayList.add(jpy);
        Currency euro = new Currency("2", "Euro");
        currencyArrayList.add(euro);
    }

    public int getCurrencyImage() {
        switch (getId()) {
            case "0":
                return R.drawable.ic_money;
            case "1":
                return R.drawable.ic_yen;
            case "2":
                return R.drawable.ic_euro;
        }
        return R.drawable.ic_money;
    }

    public static ArrayList<Currency> getCurrencyArrayList() {
        return currencyArrayList;
    }

    // 新增根据ID获取货币实例的方法,统一映射逻辑
    public static Currency getCurrencyById(String id) {
        for (Currency currency : currencyArrayList) {
            if (currency.getId().equals(id)) {
                return currency;
            }
        }
        // 匹配不到返回默认美元
        return currencyArrayList.get(0);
    }
}

2. 修复BudgetTrackerSettingsActivity.java

package com.myproject.offlinebudgettrackerappproject;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.myproject.offlinebudgettrackerappproject.adapter.CurrencySpinnerAdapter;

public class BudgetTrackerSettingsActivity extends AppCompatActivity {
    private Spinner spinner;
    private Button currencyBtn;
    private SharedPreferences sharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_budget_tracker_settings);
        Currency.initCurrencies();

        spinner = findViewById(R.id.currency_spinner);
        currencyBtn = findViewById(R.id.currency_btn);
        sharedPreferences = getSharedPreferences(Currency.PREF_NAME, MODE_PRIVATE);

        // 初始化Spinner适配器
        CurrencySpinnerAdapter currencySpinnerAdapter = new CurrencySpinnerAdapter(this, R.layout.currency_spinner_adopter,
                Currency.getCurrencyArrayList());
        spinner.setAdapter(currencySpinnerAdapter);

        // 回显已保存的货币选项
        String savedCurrencyId = sharedPreferences.getString(Currency.KEY_CURRENCY_ID, Currency.DEFAULT_CURRENCY_ID);
        for (int i = 0; i < Currency.getCurrencyArrayList().size(); i++) {
            if (Currency.getCurrencyArrayList().get(i).getId().equals(savedCurrencyId)) {
                spinner.setSelection(i);
                break;
            }
        }

        // 保存按钮点击事件仅绑定一次
        currencyBtn.setOnClickListener(view -> {
            Currency selectedCurrency = (Currency) spinner.getSelectedItem();
            SharedPreferences.Editor editor = sharedPreferences.edit();
            // 仅保存货币ID即可,不需要冗余存储名称
            editor.putString(Currency.KEY_CURRENCY_ID, selectedCurrency.getId());
            editor.apply(); // 异步写入不阻塞主线程,持久化效果和commit一致

            Toast.makeText(BudgetTrackerSettingsActivity.this, "Currency Saved", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(BudgetTrackerSettingsActivity.this, MainActivity.class);
            startActivity(intent);
            finish();
        });
    }
}

3. 修复HomeFragment.java读取逻辑

import android.content.Context;
import android.content.SharedPreferences;

// 读取保存的货币配置
SharedPreferences sharedPreferences = requireActivity().getSharedPreferences(Currency.PREF_NAME, Context.MODE_PRIVATE);
String savedCurrencyId = sharedPreferences.getString(Currency.KEY_CURRENCY_ID, Currency.DEFAULT_CURRENCY_ID);
Currency currentCurrency = Currency.getCurrencyById(savedCurrencyId);

// 直接通过货币对象设置文本和图标,不需要写冗余的if-else判断
currentCurrencyTv.setText(currentCurrency.getCurrency());
currentCurrencyTv.setCompoundDrawablesWithIntrinsicBounds(currentCurrency.getCurrencyImage(), 0, 0, 0);

额外优化说明
  • 后续新增货币类型时,只需要在Currency.initCurrencies()方法中添加新的货币实例、配置对应图标即可,不需要修改保存、读取的业务逻辑,扩展性更强
  • 所有配置键名都统一定义为常量,避免硬编码导致的键名写错、值覆盖问题
  • 去掉了冗余的if-else分支,代码量减少70%,逻辑更清晰不容易出bug

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:36:17