Asynchronous 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

我有一个正在工作的flatter应用程序,它与blocSQflite一起工作,以便从数据库中获取一些注释,并将它们显示在一个简单的视图列表中。为了更好地理解bloc模式,我想“删除”数据库部分,并用我编写的注释硬编码列表替换从数据库中获取的注释。 (我认为唯一有意义的文件是note_bloc.dart,但以防我会发布剩余的代码) 因此,实现note_bloc模式并完美工作的代码如下:

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函数中获取注释,因此当真实上下文呈现发生时,不会接收到并显示注释。