Flutter中跨类访问SharedPreferences存储的List<String>问题
嘿,我来帮你搞定这个问题!你遇到的空数组问题,大概率是因为直接拿内存里的categoryList时机不对,或者没有正确从SharedPreferences(以下简称SP)里读取序列化后的列表。不用单独新建类,咱们就在现有结构上调整就行,给你两种靠谱的方案:
方案一:给Categories类添加静态读取方法(最直接)
核心思路是:每次需要列表时,直接从SP中反序列化读取,而不是依赖Categories内存中的变量——这样能避免因初始化时机导致的空值问题。
第一步:确保Categories里的存储逻辑正确
先确认你存列表到SP时,是把List<String>转成了可存储的字符串(SP不能直接存列表),比如用Gson序列化:
// 在Categories类中,保存列表到SP的方法 public void saveCategoryListToSP(Context context, List<String> categoryList) { SharedPreferences sp = context.getSharedPreferences("CategoryPrefs", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); // 用Gson把列表转成JSON字符串 String categoryJson = new Gson().toJson(categoryList); editor.putString("saved_category_list", categoryJson); editor.apply(); // 异步保存,推荐用这个替代commit }
第二步:给Categories加静态读取方法
这样不用创建Categories实例,就能在MonthlyOverview里直接调用:
// Categories类中的静态方法,供外部获取列表 public static List<String> getCategoryListFromSP(Context context) { SharedPreferences sp = context.getSharedPreferences("CategoryPrefs", Context.MODE_PRIVATE); String categoryJson = sp.getString("saved_category_list", "[]"); // 默认空数组 // 用Gson把JSON字符串转回List<String> Type listType = new TypeToken<List<String>>() {}.getType(); return new Gson().fromJson(categoryJson, listType); }
第三步:在MonthlyOverview中调用
在合适的生命周期方法(比如onCreate或onStart)里调用静态方法:
// MonthlyOverview类中获取列表 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_monthly_overview); List<String> categoryList = Categories.getCategoryListFromSP(this); Log.d("MonthlyOverview", "获取到的分类列表:" + categoryList); // 接下来用这个列表做你需要的操作就行 }
方案二:用LiveData监听列表变化(适合实时更新场景)
如果Categories里的列表会动态修改,想让MonthlyOverview自动收到更新,可以用LiveData实现:
第一步:在Categories中添加LiveData相关逻辑
// Categories类中定义静态LiveData private static MutableLiveData<List<String>> categoryLiveData = new MutableLiveData<>(); // 初始化时从SP加载列表并更新LiveData public static void initCategoryData(Context context) { SharedPreferences sp = context.getSharedPreferences("CategoryPrefs", Context.MODE_PRIVATE); String categoryJson = sp.getString("saved_category_list", "[]"); Type listType = new TypeToken<List<String>>() {}.getType(); List<String> categoryList = new Gson().fromJson(categoryJson, listType); categoryLiveData.postValue(categoryList); } // 保存列表时同时更新LiveData public static void updateAndSaveCategoryList(Context context, List<String> newList) { SharedPreferences sp = context.getSharedPreferences("CategoryPrefs", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); String categoryJson = new Gson().toJson(newList); editor.putString("saved_category_list", categoryJson); editor.apply(); categoryLiveData.postValue(newList); // 通知所有观察者更新 } // 供外部获取LiveData的方法 public static LiveData<List<String>> getCategoryLiveData() { return categoryLiveData; }
第二步:在MonthlyOverview中观察LiveData
// MonthlyOverview类中监听列表变化 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_monthly_overview); // 先初始化数据 Categories.initCategoryData(this); // 观察列表变化,自动获取最新值 Categories.getCategoryLiveData().observe(this, new Observer<List<String>>() { @Override public void onChanged(List<String> categoryList) { Log.d("MonthlyOverview", "实时更新的分类列表:" + categoryList); // 这里处理列表更新后的UI逻辑 } }); }
注意事项
- 确保SP的名称(比如上面的
CategoryPrefs)和存储的Key(saved_category_list)在存取时完全一致,别写错! - 如果用Gson,记得在你的
build.gradle(Module级)里添加依赖:implementation 'com.google.code.gson:gson:2.10.1' - 如果不想用Gson,也可以用
TextUtils.join(",", list)把列表转成逗号分隔的字符串,取的时候用Arrays.asList(sp.getString(...).split(","))——但要注意如果列表项里包含逗号,会出错,所以Gson更稳妥。
内容的提问来源于stack exchange,提问作者Frederik
相关产品推荐
相关产品推荐

