Asynchronous Bloc模式未通过数据库就无法获取注释
我有一个正在工作的flatter应用程序,它与bloc和SQflite一起工作,以便从数据库中获取一些注释,并将它们显示在一个简单的视图列表中。为了更好地理解bloc模式,我想“删除”数据库部分,并用我编写的注释硬编码列表替换从数据库中获取的注释。 (我认为唯一有意义的文件是note_bloc.dart,但以防我会发布剩余的代码) 因此,实现note_bloc模式并完美工作的代码如下:Asynchronous Bloc模式未通过数据库就无法获取注释,asynchronous,flutter,dart,async-await,bloc,Asynchronous,Flutter,Dart,Async Await,Bloc,我有一个正在工作的flatter应用程序,它与bloc和SQflite一起工作,以便从数据库中获取一些注释,并将它们显示在一个简单的视图列表中。为了更好地理解bloc模式,我想“删除”数据库部分,并用我编写的注释硬编码列表替换从数据库中获取的注释。 (我认为唯一有意义的文件是note_bloc.dart,但以防我会发布剩余的代码) 因此,实现note_bloc模式并完美工作的代码如下: class NotesBloc implements BlocBase { final _notesCont
class NotesBloc implements BlocBase {
final _notesController = StreamController<List<Note>>.broadcast();
StreamSink<List<Note>> get _inNotes => _notesController.sink;
Stream<List<Note>> get notes => _notesController.stream;
NotesBloc() {
getNotes();
}
@override
void dispose() {
_notesController.close();
}
Future<void> getNotes() async {
List<Note> notesFromDB = await DBProvider.db.getNotes();
_inNotes.add(notesFromDB);
}
类NotesBloc实现BlocBase{
final _notesController=StreamController.broadcast();
StreamSink获取\u inNotes=>\u notesController.sink;
Stream get notes=>\u notesController.Stream;
NotesBloc(){
getNotes();
}
@凌驾
无效处置(){
_notesController.close();
}
Future getNotes()异步{
List notesFromDB=await DBProvider.db.getNotes();
_添加(notesFromDB);
}
函数DBProvider.db.getNotes()是这样编写的(只有知道):
getNotes()异步{
最终数据库=等待数据库;
var res=await db.query('note');
List notes=res.isNotEmpty?res.map((note)=>note.fromJson(note)).toList():[];
回条;
}
我尝试做的第一件事是更改notes_bloc的getNotes函数,如下所示:
void getNotes() async {
// List<Note> notesFromDB = await DBProvider.db.getNotes();
List<Note> noteHardcoded = [new Note()];
_inNotes.add(noteHardcoded);
void getNotes() async {
// List<Note> notesFromDB = await DBProvider.db.getNotes();
List<Note> noteHardcoded = await asyncNotes();
_inNotes.add(noteHardcoded);
}
asyncNotes() async {
List<Note> noteHardcoded = [new Note()];
return noteHardcoded;
}
void getNotes()异步{
//List notesFromDB=await DBProvider.db.getNotes();
列表注释硬编码=[新注释()];
_添加(注释硬编码);
}
很好,很简单,但如果我启动应用程序,它不会出错,并且会陷入无限循环,不会显示任何注释
相反,如果我只是从异步函数中获取硬编码注释,如下所示:
void getNotes() async {
// List<Note> notesFromDB = await DBProvider.db.getNotes();
List<Note> noteHardcoded = [new Note()];
_inNotes.add(noteHardcoded);
void getNotes() async {
// List<Note> notesFromDB = await DBProvider.db.getNotes();
List<Note> noteHardcoded = await asyncNotes();
_inNotes.add(noteHardcoded);
}
asyncNotes() async {
List<Note> noteHardcoded = [new Note()];
return noteHardcoded;
}
void getNotes()异步{
//List notesFromDB=await DBProvider.db.getNotes();
List noteHardcoded=WAIT asyncNotes();
_添加(注释硬编码);
}
asyncNotes()异步{
列表注释硬编码=[新注释()];
返回注释硬编码;
}
它的工作没有预期的问题!!
这就像notes集团的getNotes()只能从异步函数中调用notes,我不知道为什么
这是我使用notes\u bloc的statefull小部件代码:
class _NotesPageState extends State<NotesPage> {
NotesBloc _notesBloc;
@override
void initState() {
super.initState();
print("I'm in the initState going to assign _notesBlock");
_notesBloc = BlocProvider.of<NotesBloc>(context);
print("I'm in the initState and i assigned _notesBlock");
}
StreamBuilder<List<Note>>(
stream: _notesBloc.notes,
builder: (BuildContext context, AsyncSnapshot<List<Note>> snapshot) {
print("building context..");
// Make sure data exists and is actually loaded
if (snapshot.hasData) {
// If there are no notes (data), display this message.
if (snapshot.data.length == 0) {
return Text('No notes');
}
List<Note> notes = snapshot.data;
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Note note = notes[index];
return GestureDetector(
onTap: () {
_navigateToNote(note);
},
child: Container(
height: 40,
child: Text(
'Note ' + note.id.toString(),
style: TextStyle(
fontSize: 18
),
),
),
);
},
);
}
return Center(
child: CircularProgressIndicator(),
);
class\u notespatate扩展状态{
NotesBloc _NotesBloc;
@凌驾
void initState(){
super.initState();
打印(“我处于初始状态,将分配_notesBlock”);
_notesBloc=BlocProvider.of(上下文);
打印(“我处于初始状态,我分配了_notesBlock”);
}
StreamBuilder(
流:_notesBloc.notes,
生成器:(BuildContext上下文,异步快照){
打印(“建筑背景…”);
//确保数据存在并已实际加载
if(snapshot.hasData){
//如果没有注释(数据),则显示此消息。
如果(snapshot.data.length==0){
返回文本(“无注释”);
}
列表注释=snapshot.data;
返回ListView.builder(
itemCount:snapshot.data.length,
itemBuilder:(构建上下文,int索引){
注释=注释[索引];
返回手势检测器(
onTap:(){
_注(注);;
},
子:容器(
身高:40,
子:文本(
'Note'+Note.id.toString(),
样式:TextStyle(
尺寸:18
),
),
),
);
},
);
}
返回中心(
子对象:CircularProgressIndicator(),
);
在小部件上调用bloc getNotes()函数的位置
可能您在进入小部件之前在流中添加了信息,因此当您构建小部件时,流中没有任何价值
您可以尝试使用BehaviorSubject而不是Stream。BehaviorSubject始终发送最后一个下沉的值,因此如果我的hipothesis是正确的,它应该可以工作。谢谢!问题正是您提到的问题。使用异步等待函数,小部件首先通过initState,然后构建第一个“空白”上下文,然后(当它通过流接收到注释时)最后再次呈现小部件,并显示注释。如果没有异步函数,它会在初始化bloc(_notesBloc)后立即在initState函数中获取注释,因此当真实上下文呈现发生时,不会接收到并显示注释。