StreamBuilder 未正确刷新新值
StreamBuilder not correctly refreshing on new value
可能是我的错或一个愚蠢的错误,但这就是发生在我身上的事情:
authController.dart:
class AuthController {
BehaviorSubject _hometownController = BehaviorSubject();
Observable get hometown => _hometownController.stream;
void updateHometown(String hometown) {
_hometownController.add(hometown);
print(_hometownController.value); <- This always prints the expected value: "Hello!"`
}
}
Login_screen.dart:
class Login2 extends StatelessWidget {
AuthController authController = new AuthController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) =>
Container(
padding: EdgeInsets.all(32.0),
child: Center(
child:
//Hometown:
StreamBuilder(
stream: authController.hometown,
builder: (BuildContext context, AsyncSnapshot snap) {
return ListTile(
leading: Icon(Icons.map),
title: Text("Hometown:"),
subtitle: snap.hasData ? Text(snap.data) : Text("Not set"),
onTap: () {
authController.updateHometown("Hello!");
},
);
}
),
))));}}
一切顺利。
但是如果我在 authController.updateHometown:
之前添加一个带有 async 和 await 的异步函数
Login_screen.dart:
onTap: () async {
var x = await something(); <- This always successfully completes
authController.updateHometown("Hello!");
},
流永远不会收到新值,StreamBuilder 也永远不会重建!
但是如果我使用 statefulWidget class:
class Login2 extends StatefulWidget {
@override
State<StatefulWidget> createState() => Login2State();
}
class Login2State extends State<Login2> {
AuthController authController;
@override
void initState() {
authController = new AuthController();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) =>
Container(
padding: EdgeInsets.all(32.0),
child: Center(
child:
//Hometown:
StreamBuilder(
stream: authController.hometown,
builder: (BuildContext context, AsyncSnapshot snap) {
return ListTile(
leading: Icon(Icons.map),
title: Text("Hometown:"),
subtitle: snap.hasData ? Text(snap.data) : Text("Not set"),
onTap: () async {
var x = await something();
authController.updateHometown("Hello!");
},
);
}),))));}}
一切顺利,即使我从不调用 setState
为什么会这样?
来自 Framework.dart
:
A StatelessWidget
根据具有两个条件的数据构建自身:
- widget时可以同步读取
建成。并且:
- 可能会在小部件的生命周期内发生变化。
这就是为什么当你把Login2
做成StatelessWidget
,然后同步改变authController
中的数据时,它会立即反映出来,因为它同时满足这两个条件。但是当你在 onTap()
中使用 async
函数时,你破坏了第一个。
为什么 StatefulWidget
与 async
函数一起工作是因为它的 build
函数只需要一个数据更改就可以隐式触发 setState()
而不管这个信息是否同步可用或异步。
可能是我的错或一个愚蠢的错误,但这就是发生在我身上的事情:
authController.dart:
class AuthController {
BehaviorSubject _hometownController = BehaviorSubject();
Observable get hometown => _hometownController.stream;
void updateHometown(String hometown) {
_hometownController.add(hometown);
print(_hometownController.value); <- This always prints the expected value: "Hello!"`
}
}
Login_screen.dart:
class Login2 extends StatelessWidget {
AuthController authController = new AuthController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) =>
Container(
padding: EdgeInsets.all(32.0),
child: Center(
child:
//Hometown:
StreamBuilder(
stream: authController.hometown,
builder: (BuildContext context, AsyncSnapshot snap) {
return ListTile(
leading: Icon(Icons.map),
title: Text("Hometown:"),
subtitle: snap.hasData ? Text(snap.data) : Text("Not set"),
onTap: () {
authController.updateHometown("Hello!");
},
);
}
),
))));}}
一切顺利。 但是如果我在 authController.updateHometown:
之前添加一个带有 async 和 await 的异步函数Login_screen.dart:
onTap: () async {
var x = await something(); <- This always successfully completes
authController.updateHometown("Hello!");
},
流永远不会收到新值,StreamBuilder 也永远不会重建!
但是如果我使用 statefulWidget class:
class Login2 extends StatefulWidget {
@override
State<StatefulWidget> createState() => Login2State();
}
class Login2State extends State<Login2> {
AuthController authController;
@override
void initState() {
authController = new AuthController();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) =>
Container(
padding: EdgeInsets.all(32.0),
child: Center(
child:
//Hometown:
StreamBuilder(
stream: authController.hometown,
builder: (BuildContext context, AsyncSnapshot snap) {
return ListTile(
leading: Icon(Icons.map),
title: Text("Hometown:"),
subtitle: snap.hasData ? Text(snap.data) : Text("Not set"),
onTap: () async {
var x = await something();
authController.updateHometown("Hello!");
},
);
}),))));}}
一切顺利,即使我从不调用 setState 为什么会这样?
来自 Framework.dart
:
A StatelessWidget
根据具有两个条件的数据构建自身:
- widget时可以同步读取 建成。并且:
- 可能会在小部件的生命周期内发生变化。
这就是为什么当你把Login2
做成StatelessWidget
,然后同步改变authController
中的数据时,它会立即反映出来,因为它同时满足这两个条件。但是当你在 onTap()
中使用 async
函数时,你破坏了第一个。
为什么 StatefulWidget
与 async
函数一起工作是因为它的 build
函数只需要一个数据更改就可以隐式触发 setState()
而不管这个信息是否同步可用或异步。