我有一个非常简单的Flutter应用程序:
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Debug",
initialRoute: "/",
routes: {
"/": (context) => MainPage(),
},
);
}
}
MainPage
为:
class MainPage extends StatelessWidget {
final _rebuilder = StreamController<void>.broadcast();
@override
Widget build(BuildContext context) {
debugPrint("Initializing the app main page");
var isButtonPressed = StreamController<bool>.broadcast();
return StreamBuilder<void>(
stream: _rebuilder.stream,
builder: (context, snapshot) {
debugPrint("Rebuilding (stream = ${isButtonPressed.stream.hashCode})");
return StreamBuilder<bool>(
stream: isButtonPressed.stream,
initialData: false,
builder: (context, snapshot) {
var pressed = snapshot.data;
debugPrint("Button state: $pressed (stream = ${isButtonPressed.stream.hashCode})");
return RaisedButton(
onPressed: () {
debugPrint("Closing and rebuilding (stream = ${isButtonPressed.stream.hashCode})");
isButtonPressed.sink.add(true);
isButtonPressed.close();
isButtonPressed = StreamController<bool>.broadcast();
_rebuilder.sink.add(null);
},
child: Text("Pressed: $pressed"),
);
},
);
},
);
}
}
它使用两个StreamController
:_rebuilder
用于生成新按钮,而isButtonPressed
用于更新现有按钮。
如您所见,当按下按钮时,我会通过流的接收器对其进行更新,然后关闭流,最后要求创建一个新按钮。
但是,看起来好像是第二次创建按钮的StreamBuilder
时,由于initialData: false
尽管pressed == true
不同,所以并未使用stream.hashCode
对其进行初始化。 / p>
I/flutter ( 4207): Initializing the app main page
I/flutter ( 4207): Rebuilding (stream = 773570673)
I/flutter ( 4207): Button state: false (stream = 773570673)
I/flutter ( 4207): Closing and rebuilding (stream = 773570673)
I/flutter ( 4207): Rebuilding (stream = 786124862)
I/flutter ( 4207): Button state: true (stream = 786124862)
我不明白。我希望新流为空,因此按钮的状态为false
。为什么不这样?
答案 0 :(得分:1)
问题不在Streams中。 Streambuilder本身也使用状态方法的小部件。因此,您应该将键属性添加到Streambuilder就是这样。下面的代码。
class MainPage extends StatelessWidget {
final _rebuilder = StreamController<void>.broadcast();
@override
Widget build(BuildContext context) {
debugPrint("Initializing the app main page");
var isButtonPressed = StreamController<bool>.broadcast();
return StreamBuilder<void>(
stream: _rebuilder.stream,
builder: (context, snapshot) {
debugPrint("Rebuilding (stream = ${isButtonPressed.stream.hashCode})");
return StreamBuilder<bool>(
key: UniqueKey(),
stream: isButtonPressed.stream,
initialData: false,
builder: (context, snapshot) {
var pressed = snapshot.data;
debugPrint(
"Button state: $pressed (stream = ${isButtonPressed.stream.hashCode})");
return RaisedButton(
onPressed: () {
debugPrint(
"Closing and rebuilding (stream = ${isButtonPressed.stream.hashCode})");
isButtonPressed.sink.add(true);
isButtonPressed.close();
isButtonPressed = StreamController<bool>.broadcast();
_rebuilder.sink.add(null);
},
child: Text("Pressed: $pressed"),
);
},
);
},
);
}
}
(感谢@Delgan发现逻辑错误,答案已编辑。)