gpt4 book ai didi

flutter - Flutter StreamBuilder从先前的生成器流中生成快照

转载 作者:行者123 更新时间:2023-12-03 03:48:39 25 4
gpt4 key购买 nike

我有一个包装在另一个StreamBuilder中的StreamBuilder。内部StreamBuilder会将来自分页的异步查询的结果加载到ListView中。外部StreamBuilder会使用用户指定的搜索文本发出新查询,并构建新的内部StreamBuilder来侦听新查询。该查询使用生成器函数生成流。
我注意到一些非常奇怪的行为:
发出新查询并用新Stream重建内部StreamBuilder时,它最初会从先前的Stream接收数据。当新的Stream为空时(例如,用户的查询未产生结果),这一点尤其明显。如果新的Stream为空,则它从ConnectionState.waiting变为ConnectionState.done,并且两个事件(我认为是错误的)都填充有前一个生成器Stream的数据。
这是我编写的一些代码,它们以尽可能孤立的方式重现此代码。为了简单起见,我将外部StreamBuilder替换为FutureBuilder,尽管其行为是相同的。

import 'dart:async';

import 'package:flutter/material.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}

class MyApp extends StatelessWidget {
final Future<bool> oneSecondFuture = Future.delayed(Duration(seconds: 2), () {
print('future completed!');
return true;
});

@override
Widget build(BuildContext context) {
Stream<int> intStream(bool returnValues) async* {
var lst = [1, 2, 3];
var i = 0;
while (returnValues) {
if (i == lst.length) break;
yield lst[i++];
await Future.delayed(Duration(milliseconds: 40));
}
}

print('building');
var futureBuilder = FutureBuilder(
future: oneSecondFuture,
builder: (_, boolSnap) {
// If the future isn't complete yet, return a StreamBuilder with a nonempty stream
if (!boolSnap.hasData) return StreamBuilder(
stream: intStream(true),
builder: (_, intSnap) {
print('Nonempty steambuilder: ' + intSnap.connectionState.toString() + '; ' + intSnap.data.toString());
return Text(intSnap.data.toString());
}
);

// If the future is complete, return a StreamBuilder with an empty stream
return StreamBuilder(
stream: intStream(false),
builder: (_, intSnap) {
print('Empty steambuilder: ' + intSnap.connectionState.toString() + '; ' + intSnap.data.toString());
return Text(intSnap.data.toString());
}
);
}
);

return MaterialApp(
title: 'Test StreamBuilder',
home: futureBuilder,
);
}
}
上面的代码产生以下打印输出:
I/flutter (20225): building
I/flutter (20225): Nonempty streambuilder: ConnectionState.waiting; null
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 1
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 2
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 3
I/flutter (20225): Nonempty streambuilder: ConnectionState.done; 3
I/flutter (20225): building
I/flutter (20225): Nonempty streambuilder: ConnectionState.waiting; 3
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 1
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 2
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 3
I/flutter (20225): Nonempty streambuilder: ConnectionState.done; 3
I/flutter (20225): future completed!
I/flutter (20225): Empty streambuilder: ConnectionState.waiting; 3
I/flutter (20225): Empty streambuilder: ConnectionState.done; 3
请注意,在等待连接时,第二个构建以最后一个流的值“3”开始。空流对于等待事件和完成事件均产生值为3的值。
如果我创建另一个相同的intStream函数(即intStream和intStreamTwo)并在将来完成后调用它,则将按预期获得空数据值,因此看来问题出在重复调用单个生成器函数以获取不同的流:
I/flutter (20225): building
I/flutter (20225): Nonempty streambuilder: ConnectionState.waiting; null
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 1
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 2
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 3
I/flutter (20225): Nonempty streambuilder: ConnectionState.done; 3
I/flutter (20225): building
I/flutter (20225): Nonempty streambuilder: ConnectionState.waiting; 3
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 1
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 2
I/flutter (20225): Nonempty streambuilder: ConnectionState.active; 3
I/flutter (20225): Nonempty streambuilder: ConnectionState.done; 3
I/flutter (20225): future completed!
I/flutter (20225): using a different generator function:
I/flutter (20225): Empty streambuilder: ConnectionState.waiting; null
I/flutter (20225): Empty streambuilder: ConnectionState.done; null
这是预期的行为吗?有没有一种让我可以让StreamBuilder不接收来自先前生成器Stream的数据的明智方法?我想我可以创建两个相同的生成器函数并在它们之间交替,但是我真的很想在这里找到一个不太麻烦的解决方案。

最佳答案

我已经通过仔细阅读文档回答了自己的问题。这似乎是(令人难以置信的)预期行为。参见documentation
但是,我仍然不清楚为什么使用来自相同生成器函数的新流将触发此行为,而使用来自不同生成器函数的新流却不会触发此行为。
无论哪种方式,对于任何其他面临相同问题的人,我打算解决的方法是在ConnectionState为“waiting”或“done”时忽略错误的数据值,只要流为空(例如,“done”快照)却没有收到有效的事件值)。

关于flutter - Flutter StreamBuilder从先前的生成器流中生成快照,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64518456/

25 4 0
文章推荐: javascript - 使用 JavaScript 将多个值附加到