Flutter:setState()在封闭函数返回之前不会执行。

14 浏览
0 Comments

Flutter:setState()在封闭函数返回之前不会执行。

所以我在Flutter中尝试了这段代码:

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {

@override

_MyAppState createState() => _MyAppState();

}

class _MyAppState extends State {

int _i = 1;

@override

Widget build(BuildContext context) {

return MaterialApp(

home: Scaffold(

body: Center(

child: MaterialButton(

child: Text('You Pressed Me $_i'),

onPressed: () {

setState(() {

_i++;

print('inside i = $_i');

});

sleep(Duration(seconds: 10));

_i++;

print('outside i = $_i');

}

),

),

),

);

}

}

期望的行为(运行并按下按钮后):按钮显示文本"你按了我2次",然后变量_i增加到3,但不影响视觉结果。

实际行为:执行setState(),然后_i再次增加,但没有视觉变化,即屏幕上的文本不会更新,当onPressed()返回时,setState()导致小部件重建并更新屏幕,10秒后屏幕上显示的是"你按了我3次"。

关于setState(),文档中有这样一句话:

提供的回调立即同步调用。它不能返回一个future(回调不能是异步的),因为这样就不清楚何时实际设置状态。

我理解这个调用是同步的(根据这个答案,它是阻塞的),所以它应该先返回(这已经发生了),然后更新屏幕(或计划在将来某个时间进行),然后返回控制给后续行(后两个步骤都没有发生)。

我甚至尝试了没有sleep的情况,但结果相同。

那么我错过了什么或者误解了什么?

0
0 Comments

Flutter中的setState()方法不会在封闭函数返回之前执行的问题是由以下原因引起的:setState()方法会立即运行传递的函数,并且只是将小部件标记为"dirty",而不会直接操作状态。解决方法是使用WidgetsBinding.instance.addPostFrameCallback()方法,在小部件重建之后运行代码。

具体来说,当调用setState()时,传递的闭包函数会立即执行,并且会将小部件标记为"dirty",但不会直接修改状态。在示例中,尽管闭包函数将状态s设置为"1",但在闭包函数之后,该状态又被修改为"2"。因此,状态s的最终结果是"2"。

解决这个问题的方法是在闭包函数之外直接更新状态。这样,闭包函数只负责将小部件标记为"dirty",而不会修改状态。

另一种解决方法是手动处理StatefulWidget的元素创建,并手动标记它。但是,这种方法并不推荐使用。

为了在小部件重建之后运行代码,可以使用addPostFrameCallback()方法。具体实现请参考以下示例代码:

class _MyWidgetState extends State {

String s = "";

onPressed: () {

this.s = "1";

setState(() {

// Implementation of setState calls

// _element.markNeedsBuild();

});

}

@override

void initState() {

super.initState();

WidgetsBinding.instance.addPostFrameCallback((_) {

// doStuffAfterNextBuild

});

}

// Widget build()...

}

通过将要在小部件重建之后运行的代码放在addPostFrameCallback()的回调函数中,可以确保代码在小部件重建之后执行。

总之,setState()方法不会在封闭函数返回之前执行,这是由于其立即执行传递的闭包函数并将小部件标记为"dirty"。为了在小部件重建之后运行代码,可以使用addPostFrameCallback()方法。

0
0 Comments

Flutter中的setState()方法是用于更新widget状态的。然而,有一个问题是,setState()方法并不会立即执行,而是在包含它的函数返回后才执行。

这个问题的原因是Flutter中的事件循环(Event Loop)的存在。事件循环按顺序处理事件,而setState()方法是一个事件。下面是一个事件循环中的示例:

1. 事件A:用户点击触发的事件

2. 事件B:操作系统提供的Vsync信号

在上述示例中,事件A中包含了一个点击事件处理函数,其中调用了setState()方法。然而,该方法并不会立即执行,而是在函数返回后才执行。这是因为事件循环会按顺序处理事件,而setState()方法是一个事件,必须等待其他事件处理完成后才能执行。

为了解决这个问题,可以使用PostFrameCallback来在widget构建完成后执行任务。可以使用以下代码来添加一个PostFrameCallback:

WidgetsBinding.instance.addPostFrameCallback((_) {

// 在构建完成后执行任务

});

通过使用PostFrameCallback,可以在widget构建完成后执行一些任务,以解决setState()方法执行延迟的问题。

希望通过上述内容的整理,对Flutter中setState()方法不会立即执行的原因以及解决方法有了更清晰的理解。

0