首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么每当类被刷新类调用时,我的initstate就会被调用?

在Flutter中,initState 方法是在一个 StatefulWidget 的生命周期中最早被调用的方法之一。它在 State 对象被插入到组件树中之后立即被调用,并且只被调用一次。如果你发现 initState 在每次类被刷新时都被调用,这通常不是正常的行为,因为 initState 应该只在 State 对象创建时调用一次。

这种情况可能是由于以下原因造成的:

  1. StatefulWidget 被重建:如果你的 StatefulWidget 被重建了,那么新的 State 对象会被创建,从而导致 initState 被再次调用。这可能是因为父组件重新构建,或者是因为你手动调用了 setState 方法。
  2. 路由变化:如果你的应用使用了路由(如 Navigator),当从一个页面导航到另一个页面时,之前的页面的 State 可能会被销毁并重新创建。
  3. 状态管理问题:如果你使用了某种形式的状态管理(如 Provider、Riverpod 等),状态的变化可能导致 widget 树被重建。
  4. 代码逻辑问题:可能在某些地方你错误地重新创建了 StatefulWidget,而不是重用已有的 State。

解决方法

  • 确保 StatefulWidget 的 key 是稳定的:如果你在构建方法中使用了 Key,确保它是稳定的,这样 Flutter 才能正确地识别并重用 State 对象。
代码语言:txt
复制
class MyWidget extends StatefulWidget {
  final Key key;

  MyWidget({required this.key}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}
  • 避免不必要的 setState 调用:只在必要时调用 setState,因为它会触发 widget 的重建。
  • 使用稳定的状态管理:如果你使用状态管理库,确保你理解它是如何工作的,并且正确地使用了它。
  • 检查路由逻辑:确保在路由变化时,你没有意外地销毁和重建了 State。

示例代码

代码语言:txt
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('State Management Example'),
        ),
        body: MyWidget(key: ValueKey('unique_key')),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  final Key key;

  MyWidget({required this.key}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  void initState() {
    super.initState();
    print('initState called');
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Hello World'),
    );
  }
}

在这个例子中,我们为 MyWidget 提供了一个稳定的 Key,这样 Flutter 就可以尝试重用现有的 State 对象,而不是每次都创建一个新的。

如果你遵循了上述建议,但 initState 仍然被多次调用,可能需要进一步检查你的代码逻辑,或者提供更多的上下文信息来确定问题的根源。

参考链接:

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Flutter 组件 | ValueListenableBuilder 局部刷新小能手

每当监听的对象值发生变化时,会触发builder 方法进行刷新。如下,在点击时只需要改变 _counter.value 的值,就会触发 _buildWithValue 从而将界面数字刷新。...局部刷新的思考 这样就实现了局部刷新,可以看出 Build 的时间少了很多,比起之前的全面刷新就会有所优化。注意,这里的很多帧是由于 FloatingActionButton 的水波纹效果。...水波纹的效果也是在 RawMaterialButton 被点击时通过 setState 来刷新实现的。这也是另一种局部刷新实现的方式:组件分离,将状态变化的刷新封装在组件内部,向外界提供操作接口。...比如,现在当进度刷新时,不会触发 _buildTitle 方法,这说明 tag2 之下的组件没有被构建。...触发 build 方法,从而触发 widget.builder 回调,这样就实现了局部刷新。

8.3K41
  • 提到生命周期,我们是在说什么?

    我们可以通过初始化方法,接收父Widget传递过来的初始化UI配置参数,这些配置参数决定了Widget的最初配置效果 initState,会在State对象被插入视图树的时候调用,这个函数在State的生命周期中只会被调用一次...接下来,我和你分析一下这三个方法分别在什么场景下调用。 setState:我们最熟悉的方法之一。...当状态数据发生变化时,我们总是通过调用这个方法告诉Flutter:“我这儿的数据变啦,请使用更新后的数据重建UI!”...接下来,我们一起来看一下它们的具体调用机制: 当组件的可见状态发生变化时,deactivate函数会被调用,这时Sate会被暂时从视图树中移除。...下面这张表格,从功能、调用时机和调用次数的维度总结了上面的这些方法,帮助你去理解、记忆: ?

    1.7K10

    【Flutter】Flutter 页面生命周期 ( 初始化期 | createState | initState | 更新期 | build | 销毁期 | dispose)

    更新期的生命周期函数 /// 方法调用时机 : /// ① 调用完 didChangeDependencies 方法后调用该方法 /// ② 调用 setState 方法之后 , 该方法也会被调用...销毁期的生命周期函数 /// 方法调用时机 : 该生命周期方法不经常调用 , 只有在组件被移除时才调用 /// 该方法在 dispose 方法之前被调用 @override void deactivate...调用时机 : 组件被销毁时调用 , 要在该方法中进行资源的释放与销毁操作 ; /// 7 ....更新期的生命周期函数 /// 方法调用时机 : /// ① 调用完 didChangeDependencies 方法后调用该方法 /// ② 调用 setState 方法之后 , 该方法也会被调用...销毁期的生命周期函数 /// 方法调用时机 : 该生命周期方法不经常调用 , 只有在组件被移除时才调用 /// 该方法在 dispose 方法之前被调用 @override void deactivate

    4.4K00

    Flutter中State深入分析理解

    对象被创建时候,State.initState方法会被调用; initialized:当State对象被创建,但还没有准备构建时,State.didChangeDependencies在这个时候会被调用...; ready:State对象已经准备好了构建,State.dispose没有被调用的时候; defunct:State.dispose被调用后,State对象不能够被构建。...create 状态 ,需要注意的是此时 是在 StatefulElement 的构造函数中执行的,之后会在 StatefulElement 的 _firstBuild 方法中回调 initState方法...= null; StatefulElement 的创建 是在 回调 initState方法 之前,如下代码清单1-3 中所示,StatefulElement 继承于 ComponentElement,在父类...之后 State 的状态 更新 为 ready 状态 ,当前(StatefulElement)回调父类(ComponentElement)的 _firstBuild 方法 ,在 ComponentElement

    40211

    Flutter | 和小老弟一起玩转Widget

    setState会导致整个widget全部重建,所以在使用时,我们应该尽量把 子widget 抽离出去,采用局部刷新的方式优化,当然这个技巧具体可以百度或者参阅我之前的代码,并不是什么骚操作,基本入门技巧吧...State生命周期 initState() 当 Widget 第一次插入到 Widget树时被调用。对于每一个 State 对象,Flutter framework只会调用一次回调。...build() 主要用于构建 Widget 子树时被调用,它会在如下场景被调用: 在调用 initState 之后 调用 didUpdateWidget 之后 调用 setState 之后 调用 didChangeDependencies...之后 在 State 对象从树中一个位置移除后,又重新插入到树的其它位置之后 reassemble() 此回调是专门为开发调试而提供,在热重载 (hot reload) 时被调用,此回调在 release...下永远不会被调用。

    91620

    【Flutter 组件】001-关于 Widget 的一切

    State生命周期 图示 说明 initState:当 widget 第一次插入到 widget 树时会被调用,对于每一个 State 对象,Flutter 框架只会调用一次该回调,所以,通常在该回调中做一些一次性的操作...Inherited widget 发生了变化,那么此时 InheritedWidget 的子 widget 的didChangeDependencies()回调都会被调用。...需要注意,组件第一次被创建后挂载的时候(包括重创建)对应的 didChangeDependencies 也会被调用。...build():此回调读者现在应该已经相当熟悉了,它主要是用于构建 widget 子树的,会在如下场景被调用: 在调用 initState() 之后; 在调用 didUpdateWidget() 之后...reassemble():此回调是专门为了开发调试而提供的,在热重载(hot reload)时会被调用,此回调在 Release 模式下永远不会被调用。

    11310

    Flutter 绘制探索 6 | 深入分析 CustomPaint 组件 | 七日打卡

    在上面的绘制之后,会调用 _setRasterCacheHints 方法来设置绘制上下文中的属性,最后属性被设置给 _currentLayer。...CustomPaint 的 size 可能你在使用 CustomPainter#paint 方法内回调的 size 对象时,有些困惑,为什么有时候会是 Size(0,0),那么这里来一起探索一下回调的...=null ,会使用孩子的size 。这就是所谓的 约束自上而下传递,尺寸自下而上设置。 ? 这样,CustomPaint 的所有属性,就已经介绍完毕,当了解完其内部原来,在使用时就会游刃有余。...当遇到动态绘制和确定画板尺寸时,这些知识会让你有一个最明智的决策,而不是乱用setState刷新,或不敢用回调的 size 进行处理。...---- @张风捷特烈 2021.01.16 未允禁转 我的公众号:编程之王 联系我--邮箱:1981462002@qq.com -- ~ END ~

    1.6K10

    vue的那些原理题?(面试版)

    前言在之前面试的时候我自己也经常会遇到一些vue原理的问题, 我也总结了下自己的经常的用到的,方便自己学习,今天也给大家分享出来, 欢迎大家一起学习交流, 有更好的方法欢迎评论区指出, 后序我也将持续整理总结..., 所以对视图更新做一个异步更新的队列,避免重复计算和不必要的 DOM 操作,在下一轮时间循环的时候刷新队列,并执行已去重的任务(nextTick 的回调函数),更新视图export function...p.then(flushCallbacks); // ios 中可能会出现一个回调被推入微任务队列,但是队列没有刷新的情况 // 所以用一个空的计时器来强制刷新任务队列 if...pending) { // 如果异步开关是开的,就关上,表示正在执行回调函数,然后执行回调函数 pending = true; timerFunc(); } // 如果没有提供回调...install 方法,调用 install 方法的时候,会将 vue 作为参数传入,install 方法被同一个插件多次调用时,插件也只会被安装一次作用:注册插件,此时只需要调用 install 方法并将

    62420

    vue这些原理你都知道吗?(面试版)

    前言在之前面试的时候我自己也经常会遇到一些vue原理的问题, 我也总结了下自己的经常的用到的,方便自己学习,今天也给大家分享出来, 欢迎大家一起学习交流, 有更好的方法欢迎评论区指出, 后序我也将持续整理总结..., 所以对视图更新做一个异步更新的队列,避免重复计算和不必要的 DOM 操作,在下一轮时间循环的时候刷新队列,并执行已去重的任务(nextTick 的回调函数),更新视图export function...p.then(flushCallbacks); // ios 中可能会出现一个回调被推入微任务队列,但是队列没有刷新的情况 // 所以用一个空的计时器来强制刷新任务队列 if...pending) { // 如果异步开关是开的,就关上,表示正在执行回调函数,然后执行回调函数 pending = true; timerFunc(); } // 如果没有提供回调...install 方法,调用 install 方法的时候,会将 vue 作为参数传入,install 方法被同一个插件多次调用时,插件也只会被安装一次作用:注册插件,此时只需要调用 install 方法并将

    47330

    【源码篇】Flutter Bloc背后的思想,一篇纠结的文章

    Bloc框架做了一些让我非常疑惑的操作,_startListening方法中的回调中调用了 e.markNeedsNotifyDependents() ,完全没用!...为了验证我的想法,我debug了 framework层的notifyClients方法,调用emit或yield刷新的时候, _dependents的map一直为空,哎。。。...emit做了一个判断,如果传入state和存储state对象相同,将不执行刷新操作(这就是我在State类里面,加clone方法的原因) 初始化了Stream一系列对象 封装了关闭Stream流的操作...mapEventToState中,然后mapEventToState回传State对象 然后触发listen回调,listen中,将state传emit中,然后触发刷新控件重建 总结 上面几个关键的类分析完...,整个Bloc的运行机制,一下子就明朗了 BlocProvider 负责储存 传入XxxBloc加以储存 提供的of方法,可以在BlocProvider或其子节点位置,获取到储存的XxxBloc 提供回收资源的回调

    2.4K41

    【源码篇】Flutter GetX深度剖析 | 我们终将走出自己的路(万字图文)

    变量 将自身实例赋值给父类Element的 _inheritedWidgets 变量,key为其widget的runtimeType 为什么任何一个Widget的Element实例的 _inheritedWidgets...和传入key相同的数据,传入的数据将不会被存储 也就是说相同类实例的对象,传入并不会被覆盖,只会存储第一条数据,后续被放弃 最后使用find方法,返回传入的实例 class GetInstance {...; } } 关键步骤 通过泛型获取注入的GetXController实例 添加监听代码 addListener:添加监听回调 addListenerId:添加监听回调,必须设置id,update刷新的时候也必须写上配套的...,再现俩套经典的机制 依赖注入 在做刷新机制前,首先必须写一个依赖注入的类,我们需要自己管理逻辑层的那些实例 我这边写了一个极其简单,仅实现三种基础功能:注入,获取,删除 ///依赖注入,外部可将实例,...,自动回收依赖实例是个蛋筒的问题,此处我写了一个回收控件,可以解决此问题 使用时,必须套一层了;如果大家有更好的思路,麻烦在评论里告知 class EasyBindWidget extends StatefulWidget

    4.4K52

    【-Flutter 探索-】AutomaticKeepAliveClientMixin 保持 State 状态

    ---- 然后滑动一下列表,看一下 State 方法回调的情况。在下滑到底时,可以看到在 13 之后 0 被 dispose 了,然后前面几个 item 随着滑动被逐步 dispose。...是不是感觉很神奇,可能一般的介绍文章到这里就结束了,毕竟已经解决了问题。但可惜,这是在我的 bgm 中。...children 被 AutomaticKeepAlive 组件包裹, /// 以便children可以使用 [KeepAliveNotification] 来保存它们的状态, /// 否则它们将在屏幕外会被作为垃圾收集...注释说,此方法被触发时,就表示该组件不再需要保持状态了。...build 中也是确保在 _keepAliveHandle 为 null 时,执行 _ensureKeepAlive,这也是为什么要调用 super.build 的原因。

    2.1K30

    Flutter 绘制探索 4 | 深入分析 setState 重建和更新 | 七日打卡

    CustomPainter 类 ---- 2.关于 State#setState 我只是一把刀,英雄可以拿我除暴安良,坏蛋可以拿我屠戮无辜。...我会因英雄的善举而被赞美,也会因坏蛋的恶行而被唾弃。然而,我无法决定自己的好坏,毕竟我只是一把刀,一个工具。我只能祈祷着被他人的善用,仅此而已。...Window#scheduleFrame 是一个 native 方法,通过注释可以知道,该方法会在下一次适当的时机调用onBeginFrame 和 onDrawFrame 回调函数。 ?...所以说无论什么局部刷新,内部的原理都和 State#setState 是一样的。基本上都是对 setState 的一层封装。我们不能因为看不到 State#setState 的存在,就否定它的价值。...现在来终结一下 Custompainter#shouldRepaint 只是在当 RenderCustomPaint 设置画板属性的时候才会被回调。

    2K20

    【源码篇】Flutter Provider的另一面(万字图文+插件)

    为什么触发监听逻辑,能导致相应控件刷新?...,只会在第一次build的时候触发 这里可以确定_CreateInheritedProvider类中的createState方法一定会被调用;接下来看看其方法里面调用的 _CreateInheritedProviderState...底下也调用了 startListening,说明从外面传进来的这个回调也调用了,将 上下文实例 和 传进来的XxxProvider实例 作为入参传进了这个回调中,此处传进来的回调也通过 .call 被调用了...performRebuild回调中会赋初值 在reassemble回调中,_delegateState调用了value( _delegateState.value ) 所以 get value 肯定会在初始化的时候被调用...BuildContext 每个抽象方法上面注释超级多,我删掉了(占篇幅),有兴趣的可以自己去源码里看看 BuildContext就是抽象类,是约定好的一个抽象类,相关方法的功能已经被约定,你如果想实现这个抽象类类

    1.5K61

    Flutter开发·Flutter中动画的实现与使用

    Flutter中动画的核心类库是Animation,它并不是一个widget,Animation是一个抽象类,就相当于一个定时器,用来描述当前动画的开始,暂停,以及数值状态,与ui渲染没有任何关系,它不能直接控制...:为动画添加一个屏幕刷新的回调,每次屏幕刷新都会调用TickerCallback,目的是使用Ticker来驱动动画会防止屏幕外动画(动画的UI不在当前屏幕时,如锁屏时)消耗不必要的资源。...为这个控制器添加listener监听,每次控制器的value发生改变时监听中都会收到回调。...前面说Animation不负责ui的变化,所以这里要在监听中调用setState方法使得ui可以响应到控制器的数值变化。...Tween类中提供了两个泛型参数begin和end,也就是你可以指定你要进行变化的属性值,比如有很多Flutter中已经封装好的继承自Tween的补间动画类:ColorTween,SizeTween,BorderTween

    1.6K00

    Flutter--Flutter中Widget、App的生命周期

    其生命周期流程图则如下所示,下图中所有方框都是StatefulWidget中可以重写的方法,这些方法在响应的生命周期状态下会被自动回调。 ?...State,当组件从组件树中移除,然后重新插入到组件树中时, createState 函数将会被调用创建一个新的 State。...1.2.2 生命周期二:initState initState 函数在组件被插入树中时被 Framework 调用(在 createState 之后),此函数只会被调用一次,子类通常会重写此方法,在其中进行初始化操作...另外,当此 State 对象的依赖项更改时被调用,比如其所依赖的 InheritedWidget 发生变化时, Framework 会调用此方法通知组件发生变化。...为什么要加上如此判断?因为如果当前组件未插入到树中或者已经从树中移除时,调用 setState 会抛出异常,加上 mounted 判断,则表示当前组件在树中。

    3K31
    领券