Flutter基于SharedPreferences切换页面异常:始终显示sports分类
问题分析与解决方案
核心问题
- NewsScreen重复创建Cubit实例:NewsScreen中通过
BlocProvider(create: (context) => NewsCubit()...)生成了全新的NewsCubit,与HomeScreen使用的Cubit完全隔离,新实例的catergorieModel为null,因此触发默认值'sports'。 - Cubit初始化未读取缓存:应用启动时,NewsCubit没有主动从SharedPreferences加载保存的分类ID,导致初始状态无法匹配用户之前的选择。
- onClick方法逻辑错误:当前onClick中保存的是
this.catergorieModel!.id,但此时this.catergorieModel还未赋值,应该使用传入的参数catergorieModel的ID,且需先更新状态再保存缓存。
修复步骤
1. 共享全局Cubit,移除NewsScreen中的BlocProvider
确保整个应用使用同一个NewsCubit实例,建议在应用根节点(如MaterialApp外层)提供BlocProvider,修改NewsScreen直接复用已有Cubit:
class NewsScreen extends StatelessWidget { static const String routeName = 'news_screen'; const NewsScreen({super.key}); @override Widget build(BuildContext context) { return BlocConsumer<NewsCubit, HomeState>( listener: (context, state) { if (state is HomeSorcesSuccessState) { NewsCubit.get(context).getNewsData(); } }, builder: (context, state) { var cubit = NewsCubit.get(context); if (state is HomeLoadindState) { return const Center(child: CircularProgressIndicator()); } else if (state is HomeSorcesErrorState) { return const Center(child: Text('No News')); } return Column( children: [ const TabBarWidget(), Expanded( child: ListView.builder( itemCount: cubit.articlesList.length, itemBuilder: (context, index) { return ArticlesNewsWidget( articles: cubit.articlesList[index], ); }, ), ) ], ); }, ); } }
2. 在NewsCubit初始化时加载缓存
修改NewsCubit构造函数,启动时自动读取SharedPreferences中的分类ID并更新状态:
class NewsCubit extends Cubit<HomeState> { NewsCubit() : super(HomeInitialState()) { _loadSavedCategory(); } // 假设categories列表在Cubit中可访问,或通过参数传入 List<CatergorieModel> categories = [/* 分类数据 */]; CatergorieModel? catergorieModel; Future<void> _loadSavedCategory() async { String? savedCategoryId = await CasheHelper.getData('news'); if (savedCategoryId != null) { catergorieModel = categories.firstWhere((cat) => cat.id == savedCategoryId); getSources(savedCategoryId); emit(NewsView()); } } // 现有getSources、getNewsData等方法... }
3. 修复onClick方法的逻辑
更新onClick,先赋值状态再保存缓存:
void onClick(CatergorieModel catergorieModel) { this.catergorieModel = catergorieModel; CasheHelper.saveData('news', catergorieModel.id); getSources(catergorieModel.id); emit(NewsView()); }
4. 简化HomeScreen的判断逻辑
由于Cubit初始化时已读取缓存,HomeScreen无需直接判断SharedPreferences:
body: NewsCubit.get(context).catergorieModel == null ? // 分类选择界面 : const NewsScreen(),
内容的提问来源于stack exchange,提问作者omar maamoun
相关产品推荐
相关产品推荐

