flutter_bloc结合freezed开发时Cubit获取sqflite数据返回值始终为null
问题原因
- 未触发数据读取逻辑:按钮的
onPressed回调里仅打印了当前状态,从未调用DisplayNoteCubit的getData()方法,数据库读取逻辑全程没有执行,自然拿不到数据。
- 未触发数据读取逻辑:按钮的
- Cubit的
getData()逻辑写反:当前getData()方法仅在状态已经是DisplayNoteState.getData类型时才会执行读库逻辑,但初始状态为DisplayNoteState.initial,所以state.maybeMap只会走orElse分支,读库和emit操作永远不会执行。
- Cubit的
- 状态更新时机不匹配:就算触发了
getData(),读库是异步操作,在点击的同步回调里直接打印旧状态,也拿不到刚读取的新数据。
- 状态更新时机不匹配:就算触发了
修复方案
第一步:修正Cubit的getData逻辑
删除原有状态判断逻辑,调用getData时直接读取数据库,再emit新状态:
final DBHelper _db=DBHelper.instance; class DisplayNoteCubit extends Cubit<DisplayNoteState> { DisplayNoteCubit() : super(const DisplayNoteState.initial()); // 改为异步方法,方便调用时等待执行完成 Future<void> getData() async { final notes = await _db.getAllNotesFormDB(); emit(DisplayNoteState.getData(notes: notes)); } }
第二步:修正按钮点击逻辑
点击时先触发数据读取方法,等待异步执行完成后再打印新状态:
BlocBuilder<DisplayNoteCubit, DisplayNoteState>( builder: (context, state) { return MaterialButton( onPressed: () async { // 先触发读数据逻辑,等待执行完成 await context.read<DisplayNoteCubit>().getData(); // 状态更新后再打印结果 if(context.mounted) { print( '\n print all Data \n ${context.read<DisplayNoteCubit>().state.maybeMap( orElse: () => null, getData: (g) => g.notes )}'); } }, child: const Text("Click Me"), ); }, ),
可选优化:页面加载时提前拉取数据
如果需要页面打开就加载数据,可以在页面initState阶段调用getData,后续直接在BlocBuilder中根据状态渲染UI即可:
BlocBuilder<DisplayNoteCubit, DisplayNoteState>( builder: (context, state) { return state.maybeMap( orElse: () => const CircularProgressIndicator(), getData: (g) => ListView.builder( itemCount: g.notes.length, itemBuilder: (context, index) => Text(g.notes[index]['content'].toString()), ), ); }, )
内容的提问来源于stack exchange,提问作者Mariam Albarghouti
相关产品推荐
相关产品推荐

