简体   繁体   English

我什么时候在 Flutter 中使用 setState?

[英]When do I use setState in Flutter?

As newbie in flutter it's very confusing for me when use setState in Flutter application.作为 flutter 的新手,在Flutter应用程序中使用setState时对我来说非常困惑。 In below code boolean searching and var resBody used inside setState .在下面的代码中,布尔searching和 var resBodysetState My question is why only searching and resBody inside setState?我的问题是为什么只在 setState 中searchingresBody Why not others variable?为什么不是其他变量?

var resBody;
bool searching =  false,api_no_limit = false;
String user = null;

Future _getUser(String text) async{
setState(() {
  searching = true;
});
user = text;
_textController.clear();
String url = "https://api.github.com/users/"+text;
  var res = await http
      .get(Uri.encodeFull(url), headers: {"Accept": 
           "application/json"});
  setState(() {
    resBody = json.decode(res.body);
  });
}

According to the docs :根据文档

Calling setState notifies the framework that the internal state of this object has changed in a way that might impact the user interface in this subtree, which causes the framework to schedule a build for this State object.调用 setState 通知框架此对象的内部状态已更改,可能会影响此子树中的用户界面,这会导致框架为此 State 对象安排构建。

So if the state of the widget changes you have to call setState to trigger a rebuild of the view and see immediatly the changes implied by the new state.因此,如果小部件的状态发生变化,您必须调用setState来触发视图的重建并立即查看新状态所隐含的更改。

Anyhow the below snippets are equivalent.无论如何,以下片段是等效的。

first case (directly form flutter create <myproject> ):第一种情况(直接形成flutter create <myproject> ):

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {

    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

second case:第二种情况:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    _counter++;
    setState(() {});
  }

What I don't know is the reason why and if the first case is the conventional way to use setState , I would say because of readability of code.我不知道是为什么以及如果第一种情况是使用setState的常规方法,我会说是因为代码的可读性。

When you change the state of a stateful widget, use setState() to cause a rebuild of the widget and it's descendants.当您更改有状态小部件的状态时,请使用setState()来重建小部件及其后代。
You don't need to call setState() in the constructor or initState() of the widget, because build() will be run afterwards anyway.您不需要在小部件的构造函数或initState()中调用setState() ,因为无论如何都会在之后运行build()

Also don't call setState() in synchronous code inside build() .也不要在build()内的同步代码中调用setState() build() You shouldn't need to cause a rerun of build() from within build() .你不应该需要引起的重播build()从内部build()

If you look at the implementation of setState :如果您查看setState的实现:

  void setState(VoidCallback fn) {
    assert(fn != null);
    assert(...);
    final dynamic result = fn() as dynamic;
    assert(...);
    _element.markNeedsBuild();
  }

you see that the only things it does are: asserting a few things to help you debug incorrect usage of it, executing the callback, and marking the element so it gets rebuild.你会看到它唯一做的事情是:断言一些事情来帮助你调试它的错误使用,执行回调,并标记元素以使其重建。

So, technically, it doesn't matter if you change some variables inside the setState callback or outside of it, as long as setState is called.因此,从技术上讲,只要setState被调用,在 setState 回调内部或外部更改某些变量都没有关系。

However, for readability there is a big difference.但是,对于可读性,存在很大差异。 Rebuilding widgets has impact on the performance of the app, so you want to do so as little as possible.重建小部件会影响应用程序的性能,因此您希望尽可能少地这样做。 Making all, and only those, changes to variables that require the widget to rebuild inside the setState callback makes it clear to people (including your future self) exactly why a rebuild is needed.对需要小部件在setState回调中重建的变量进行所有(且仅这些)更改,可以让人们(包括您未来的自己)清楚为什么需要重建。

When you need to change the value any widget shows on the screen.当您需要更改屏幕上显示的任何小部件的值时。 For example, in the app there was a task.例如,在应用程序中有一个任务。 After completion of which points should be added to the "wallet".完成后应将哪些积分添加到“钱包”中。 But the problem is that we need to refresh the app to see points on the "wallet".但问题是我们需要刷新应用才能看到“钱包”上的积分。 To solve this we use Setstate() on Button Onpressed()为了解决这个问题,我们在 Button Onpressed() 上使用 Setstate()

For example:例如:

RaisedButton(
 
 onpressed(){
    
   setstate(){
      
     points+10;

   }
 }

)

Every time the button is pressed it will refresh the widget with the new value returned by the "wallet" variable without the need to restart the entire App.每次按下按钮时,它都会使用“钱包”变量返回的新值刷新小部件,而无需重新启动整个应用程序。

According to the documentations :根据文件

Generally it is recommended that the setState method only be used to wrap the actual changes to the state, not any computation that might be associated with the change.通常建议setState方法仅用于包装对状态的实际更改,而不是任何可能与更改相关联的计算。 For example, here a value used by the build function is incremented, and then the change is written to disk, but only the increment is wrapped in the setState :例如,这里将build函数使用的值递增,然后将更改写入磁盘,但只有递增量包装在setState

 Future<void> _incrementCounter() async { setState(() { _counter++; }); Directory directory = await getApplicationDocumentsDirectory(); final String dirName = directory.path; await File('$dir/counter.txt').writeAsString('$_counter'); }

Whenever you want to update a widget tree (generally with some new data), you call setState .每当您想要更新小部件树(通常使用一些新数据)时,您都可以调用setState It can only be used in State class.它只能在State类中使用。 Here's the simple implementation:这是简单的实现:

class _MyPageState extends State<MyPage> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          onPressed: () => setState(() => _count++),
          child: Text('Count = $_count'),
        ),
      ),
    );
  }
}

setState() is only being used with statefulWidget insides flutter. setState()仅用于 statefulWidget 内部颤动。 setState() tell the flutter to rebuild the page when something defined inside the setState() changes. setState()告诉 flutter 在setState()定义的某些内容发生更改时重建页面。

NOT: setState() is a callback function. NOT: setState()是一个回调函数。

Text(questions[questionIndex])

Here I want to change the Text according to the given questions array, and on every button click, I want to increase the index by 1.在这里,我想根据给定的问题数组更改文本,并且每次单击按钮时,我都想将索引增加 1。

void answerQuesion() {
    setState(() {
      questionIndex = questionIndex + 1;
    });
    print(questionIndex);
  }

So, I have to put this index increment inside the setState() , so that flutter will rebuild the page after every change of questionIndex.因此,我必须将此索引增量放入setState() ,以便每次更改 questionIndex 后,flutter 都会重建页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter:当我可以使用全局变量并改用 setState 时,需要 state 管理库吗? - Flutter: What is the need of state management libraries when I can use global variables and use setState instead? 无法在 flutter 的脚手架外使用 setState() - Not able to use setState() outside of scaffold in flutter Flutter:使用带有 AnimatedSwitcher 的 setstate 时未重建小部件 - Flutter: Widget not rebuilt when using setstate with AnimatedSwitcher 在 flutter 中使用 Snack Bar 和 Navigator 时,如何修复“不要使用 BuildContexts accros async gaps” - How do I fix "Do not use BuildContexts accros async gaps" when using Snack Bar and Navigator in flutter 我如何在 Flutter 中使用 RGB 颜色? - How do I use RGB color in Flutter? 我什么时候应该在 Flutter 中使用 BLoC 模式? - When should I use BLoC pattern in Flutter? 如何在 flutter 中仅对一个小部件使用 setState 方法? - How to use setState method for only one widget in flutter? 我想我做了一些设置状态在颤振中不起作用的事情 - I think i have done something that's setstate is not working in flutter 更改传递的参数时,Flutter setstate 不会再次调用 build - Flutter setstate is not calling build again when the argument passed is changed Flutter:屏幕关闭时的`setState()`,或者如何检测屏幕是否打开? - Flutter: `setState()` when screen off, or how to detect if screen is on?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM