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

在构建期间调用setState()或markNeedsBuild(),在Flutter中使用FutureBuilder中的Provider和StreamBuilder

在Flutter中,setState()markNeedsBuild() 是用于更新UI状态的方法。setState() 会触发组件的重建,而 markNeedsBuild() 则是标记组件需要在下一个构建周期中重建。在构建期间调用这些方法可能会导致不可预见的行为,因为它们会干扰Flutter的正常构建流程。

基础概念

FutureBuilder 和 StreamBuilder

  • FutureBuilder 是一个用于处理异步操作(如网络请求)的Widget,它会在Future完成时重建UI。
  • StreamBuilder 是一个用于处理流数据的Widget,它会在流发出新数据时重建UI。

Provider

  • Provider 是一个状态管理库,它允许你将数据传递给组件树中的任何子组件,而不需要手动传递props。

相关优势

  • FutureBuilder:简化异步操作的处理,自动管理加载状态、错误处理和数据展示。
  • StreamBuilder:实时响应数据流的变化,适用于需要实时更新UI的场景。
  • Provider:提供了一种简洁的方式来共享状态,避免了繁琐的props传递。

类型与应用场景

  • FutureBuilder:适用于一次性异步操作,如获取用户信息、加载图片等。
  • StreamBuilder:适用于需要持续监听的数据流,如实时聊天、股票价格更新等。
  • Provider:适用于需要在多个组件之间共享的状态,如主题设置、用户认证状态等。

遇到的问题及原因

在构建期间调用 setState()markNeedsBuild() 可能会导致以下问题:

  1. 性能问题:频繁调用这些方法会导致组件不必要的重建,影响应用性能。
  2. 逻辑错误:在构建期间改变状态可能会导致UI显示不一致或逻辑混乱。

解决方法

  1. 避免在构建期间调用:确保这些方法只在必要时调用,例如在用户交互或异步操作完成后。
  2. 使用正确的生命周期方法:在 initState() 中初始化异步操作,在 dispose() 中清理资源。
  3. 利用Provider的状态管理:通过Provider来管理状态,避免在构建期间直接调用 setState()

示例代码

代码语言:txt
复制
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyModel(),
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: Text('Example')),
          body: FutureBuilderWidget(),
        ),
      ),
    );
  }
}

class MyModel extends ChangeNotifier {
  Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 2));
    return 'Data loaded';
  }
}

class FutureBuilderWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final model = Provider.of<MyModel>(context);
    return FutureBuilder<String>(
      future: model.fetchData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        } else if (snapshot.hasError) {
          return Center(child: Text('Error: ${snapshot.error}'));
        } else {
          return Center(child: Text(snapshot.data!));
        }
      },
    );
  }
}

在这个示例中,我们使用 FutureBuilder 来处理异步数据加载,并通过 Provider 来管理状态,避免了在构建期间调用 setState()。这样可以确保UI的稳定性和性能。

相关搜索:Flutter:在使用Provider构建期间调用的setState()或markNeedsBuild()在StreamBuilder内部构建期间调用setState()或markNeedsBuild()Flutter Provider - setstate或markneedsbuild()在构建过程中调用在构建期间调用setState()或markNeedsBuildFlutter -构建期间调用的setState()或markNeedsBuild()Flutter Provider带有listen false,但仍然得到错误"setState()或markNeedsBuild()在构建期间被调用“。收到错误“在构建期间调用了setState()或markNeedsBuild()”Flutter Hooks使用构建期间调用的useEffect - setState()或markNeedsBuild()获取数据在构建过程中调用setState()或markNeedsBuild()在使用提供程序生成期间调用setState()或markNeedsBuild()在构建期间调用setState()或markNeedsBuild()。尝试在flutter中创建一个简单的计时器在构建期间调用setState()或markNeedsBuild()。将GestureDetector放入容器中重构AKA后出错在构建期间调用setState()或markNeedsBuild()。导致小部件的相关错误是RoundIconButton。A RenderFlex溢出将数据传递给生成过程中调用的provider - setState()或markNeedsBuild()为什么在构建过程中会出现快照错误和调用setState()或markNeedsBuild()?颤动显示对话框在构建过程中调用的setState()或markNeedsBuild()在构建过程中调用的setState()或markNeedsBuild() -何时设置从API获取的变量的值?在flutter中不使用provider和sqflite更新图标值来自API调用的JSON数据在ListView FutureBuilder Flutter中不显示在FuturBuilder中为Flutter项目使用StreamBuilder是正确的吗?
相关搜索:
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Flutter完整开发实战详解(十五、全面理解State与Provider)

了解这个两个概念后,我们先看下图,在 Flutter 中构建一个 Widget ,首先会创建出这个 Widget 的 Element ,而事实上 State 实现跨帧共享,就是将 State 保存在Element...问题就在于前面 StatefulElement 的构建方法和 update 方法: State 只在 StatefulElement 的构建方法中创建,当我们调用 setState 触发 update...我们常说的 setState ,其实是调用了 markNeedsBuild ,markNeedsBuild 内部会标记 element 为 diry,然后在下一帧 WidgetsBinding.drawFrame...状态共享是常见的需求,比如用户信息和登陆状态等等,而 Flutter 中 InheritedWidget 就是为此而设计的,在第十二篇我们大致讲过它: 在 Element 的内部有一个 Map<Type...接着我们逐个分析 1、Delegate 既然是状态管理,那么肯定有 StatefulWidget 和 setState 调用。

3.7K21
  • Flutter | 事件循环,Future

    正文 在 Dart 中,没有多线程的概念,所谓的异步操作全部都是在一个线程里面执行的, 并且不会造成卡顿的原因就是事件循环(Event Loop), 如下图所示,在程序的运行过程中,会有两个事件...Future.whenComplete() 类似于 try catch 后面的 finnaly,无论成功和失败,最终都会执行到这里 Future.them 链式调用 //在 them 中可以接继续返回值...,就会自动调用下面的 build 函数, initialData:初始值,在 future 没完成的时候可以暂时使用该值,该值会放在 AsyncSnapshot 的 data 中,在 future...做的小游戏 在日常开发中,StreamBuilder 还是挺实用的,这次我们用 StreamBuilder 来做一个小游戏,先看效果: 从上面的动画来看,可以将其分为三个部分,第一个部分则是底部的键盘...x 轴的位置以及动画的执行时间,最后开启动画 build 中其实是很简单的,使用了 AnimatedBuilder 来监听动画,当动画值改变后则会重新 setState(),内部就是一个小按钮,记录了题目

    4.3K10

    Flutter完整开发实战详解(十一、全面深入理解Stream)

    一、Stream 由浅入深 Stream 在 Flutter 是属于非常关键的概念,在 Flutter 中,状态管理除了 InheritedWidget 之外,无论 rxdart,Bloc 模式,flutter_redux...2、Stream 四天王 从上面我们知道,在 Flutter 中使用 Stream 主要有四个对象,那么这四个对象是如何“勾搭”在一起的?他们各自又担任什么责职呢?...二、StreamBuilder 如下代码所示, 在 Flutter 中通过 StreamBuilder 构建 Widget ,只需提供一个 Stream 实例即可,其中 AsyncSnapshot 对象为数据快照...我们常用的 setState 中其实是调用了 markNeedsBuild ,markNeedsBuild 内部标记 element 为 diry ,然后在下一帧 WidgetsBinding.drawFrame...,而这也是为什么 rxdart 可以在 StreamBuilder 中直接使用的原因。

    4K41

    StatefulWidget与State

    运行中:在渲染树中存在,这一阶段涉及的生命周期函数主要有didUpdateWidget和build。 销毁:从渲染树中移除,此阶段涉及的生命周期函数主要有deactivate和dispose。...setState如何触发界面变更 在前面很多例子中我们多次使用到setState方法,来更新Element中的数据,每次当每次数据变更时我们触发setState方法,紧接着界面就跟着变化了,大家应该都知道这是...在开始了解setState方法之前我们还需要来了解下一个枚举类_StateLifecycle,它是flutter中的一个私有类,用来表示State的生命周期。...调用Element的markNeedsBuild方法 上面的1-5步流程都非常的简单,在第6步调用markNeedsBuild方法。...小结 StatefulWidget是由状态组建,我们可以使用setState方法来重新构建组建 StatefulWidget的Wdiget是通过State的Build方法构建的 setState方法将要重新构建的

    1.4K10

    Flutter 的状态管理方案:setState、BLoC、ValueNotifier、Provider

    为简单起见,此流程由三种可能的状态组成: 图上的状态可以由如下状态机表示,其中包括加载状态和认证状态: 当登录的请求正在进行中,我们会禁用登录按钮并展示进度指示器。...在 _signInAnonymously 方法中,通过调用 bloc.setIsLoading(value) 来更新 stream。...在构建自己的应用程序时,你可以根据具体情况来评估哪个方案更合适 小彩蛋:实现 Drawer 菜单 跟踪当前选择的选项也是一个状态管理问题: 我首先在自定义 Drawer 菜单中使用本地状态变量和 setState...总结如下: StatefulWidget 在 state 被删除后,不再记住自己的 state。 使用 Provider,我们可以选择在哪里存储 widget 树中的状态。...这样,即使删除使用它的小部件,状态也会被保留。 ValueNotifier 比 setState 需要更多的代码。但它可以用来记住状态,通过在 widget 树中放置适当的 Provider。

    4.6K00

    Flutter 面试知识点集锦

    Zone Dart 中可通过 Zone 表示指定代码执行的环境,类似一个沙盒概念,在 Flutter 中 C++ 运行 Dart 也是在 _runMainZoned 内执行 runZoned 方法启动...更多相关可查阅 《Flutter完整开发实战详解(九、 深入绘制原理)》 Flutter 中 Widget 不可变,每次保持在一帧,如果发生改变是通过 State 实现跨帧状态保存,而真实完成布局和绘制数组的是...Flutter 中 setState 其实是调用了 markNeedsBuild ,该方法内部标记此Element 为 Dirty ,然后在下一帧 WidgetsBinding.drawFrame...才会被绘制,这可以看出 setState 并不是立即生效的。...image ---- 通过 StreamBuilder 和 FutureBuilder 我们可以快速使用 Stream 和 Future 快速构建我们的异步控件: 《Flutter完整开发实战详解(十一

    5.2K61

    【Flutter】FutureBuilder 异步编程 ( FutureBuilder 构造方法 | AsyncSnapshot 异步计算 )

    将 异步操作 与 异步 UI 更新 结合在一起 ; 它可以将 异步操作 的结果 , 异步的 更新到 UI 界面中 ; 异步操作结果 : 网络请求 , 数据库读取 , 等耗时操作 得到的结果 ; 二、FutureBuilder...initialData; @required AsyncWidgetBuilder builder : AsyncWidgetBuilder 类型的回调函数 , 这是基于异步交互构建 Widget... snapshot , 返回值是 Widget 组件 ; AsyncSnapshot snapshot 参数中包含有异步计算的信息 ; class AsyncSnapshot {...See /// [FutureBuilder.initialData] and [StreamBuilder.initialData]. final T?...error 是异步计算接收的错误对象 ; AsyncSnapshot snapshot 中还有 hasData 和 hasError 两个属性 , hasData 用于检查该对象是否包含非空数据值

    92320

    Flutter 刷新页面:通过下拉刷新提升用户体验

    比如,如果我们使用简单的 statefule 挂件,我们通过调用 setState 用新数据来重建 rebuild 我们的 widget tree。...当在 Flutter 中实现下拉刷新,使用 Provider,我们需要通过一个 provider 来暴露一个方法来刷新数据,然后在 onRefresh 回调函数中调用该方法。...使用 BuildContext 来管理状态和导航 BuildContext 是 Flutter 中基本概念,它表示一个挂件在 widget tree 中的位置。...在复杂的 Flutter 应用程序中拉动刷新 在更复杂的 Flutter 应用程序中,下拉刷新可能和多个状态层和数据源有交互。在这种场景中,实现一个能够处理复杂性的有强大状态管理的解决方案至关重要。...当处理复杂的数据和状态时,考虑使用流 streams 或者 FutureBUilder 挂件来更新 UI,当新数据反应可用时。这保证在应用程序当前状态, UI 还是同步的,即使数据被拉取和更新。

    33510

    Flutter 构建完整应用手册-联网 顶

    从互联网上获取数据 从大多数应用程序获取互联网上的数据是必要的。 幸运的是,Dart和Flutter为这类工作提供了工具!...现在我们有一个功能,我们可以调用从互联网上获取Post! 3.用Flutter获取并显示数据 为了获取数据并将其显示在屏幕上,我们可以使用FutureBuilder小部件!...Flutter附带FutureBuilder部件,可以轻松处理异步数据源。 我们必须提供两个参数: 使用的Future。 在我们的例子中,我们将调用我们的fetchPost()函数。...在我们发送消息给测试服务器之后,它会发回相同的消息。 我们如何听取消息并显示它们? 在这个例子中,我们将使用StreamBuilder部件来侦听新消息和一个Text 部件来显示它们。...StreamBuilder部件将连接到Stream,并在每次接收到事件时使用给定的builder函数请求Flutter重建!

    2.6K20

    Flutter混编工程之通讯之路

    在具体的方法调用处,使用MethodChannel的invokeMethod来调用具体的函数,和MethodChannel本身一样,也是通过Name标志符来调用的,参数以Map的形式进行传递。...那么在具体调用的地方,使用代码如下所示。...来监听Flutter端的调用,call参数中包含了method和argument,可以用来获取调用的函数标志符和参数。...首先,我们在Flutter中构建这样一个列表,用于展示一个信息List,信息的来源是原生侧,所以,在Flutter界面的initState中,我们创建一个名为stringCodecDemo的BasicMessageChannel...❞ 另外,不管是在Flutter中,还是在原生代码中,都是可以通过Channel来向对方通信的,以BasicMessageChannel为例,原生和Flutter侧,都可以调用send函数来发送消息,也都可以设置

    1.9K20

    告别setState()! 优雅的UI与Model绑定 Flutter DataBus使用~

    Flutter开发中,大家都绕不开Widget的刷新,setState()是最简单的用法。...如何优雅的解决这个问题,不得不提到StreamBuilder,StreamBuilder是Flutter中异步构建的核心组件。许多著名的开源框架例如Bloc皆是基于此实现。...其实Flutter中还提供了一个强大组件SteamBuilder来协助我们处理控件的刷新构建。 ---- StreamBuilder ? ?...在key1的点击事件中往Stream中add数据,这样在key1的流上产生了一条数据,对应的监听者收到数据后,只更新自己的内容,不会重建其他区域。 ? ? ?...而且由于MultDataLine是mixin定义,所以我们可以在任意的类中混入使用方法。例如直接在Widget中混入改类,调用getLine方法获取到StreamBuilder。

    2.5K41

    Flutter 移动端架构实践:Widget-Async-Bloc-Service

    团队向我们展示了如何使用Provider包和ChangeNotifier,用于在组件之间传递状态的更改。...我对状态管理和app架构的看法 过去的一年中,我构建了若干大大小小的Flutter app,期间我遇到并解决了许多问题,这让我明白了状态管理没有银弹。...UI层的控件可以自由调用由BLoC或Service定义的 同步 或 异步 方法,并可以通过StreamBuilder对流进行订阅。...无论如何,我发现BLoCs在使用Firestore构建app时效果非常明显,其中数据通过流从后端流入app。 在这种情况下,通常将流进行组合或使用RxDart对其执行转换,BLoC很擅长这个。...Flutter和Firebase Udemy课程中相关深入的资料进行了补充,链接如下: Flutter&Firebase:构建一个完整的iOS和Android的应用程序

    16.1K20

    Flutter的setState更新原理和流程

    也就是只有当我们的类是有状态类的时候才能进行状态刷新,setState也是在State(有状态类)类里 解析 :framework.dart文件State类 调用 setState() 必须是没有调用过..._element.markNeedsBuild(); } setState方法除了一些条件判断就是:_element.markNeedsBuild();那我们看看markNeedsBuild。...UI 的绘制逻辑【附加】 UI 的绘制逻辑是在 Render 树中实现的,所以这里还来细看 RendererBinding 的逻辑。...在 drawFrame 中调用 buildOwner.buildScope(renderViewElement)更新 elements。...等待下一次vsync信号的到来, 然后再经过层层调用最终会调用到 Window::BeginFrame() UI 的绘制逻辑是在 Render 树中实现的 更新帧信号来临从而刷新需要重构的界面 在 drawFrame

    80920

    Flutter响应式编程:Streams和BLoC

    由于这可以对构建应用程序的方式做出重大改变,我想要一个实际示例来说明: 很可能不使用它们,但有时可能更难以编码和性能更低, 使用它们的好处同时也是 使用它们的影响,正面的和(或)负面的。...如何基于由Stream提供的数据构建Widget? Flutter提供了一个非常方便的StatefulWidget,称为StreamBuilder。...Stream; 在流中注入值的事实导致侦听它的StreamBuilder重建并“刷新”计数器; 我们不再需要State的概念,所有内容都通过Stream接收; 这是一个很大的改进,因为调用setState...第四,减少“build”的数量 不使用setState()而是使用StreamBuilder大大减少了“build”的数量。 从性能角度来看,这是一个巨大的进步。...为什么不使用InheritedWidget? 在与BLoC相关的大多数文章中,你会看到通过InheritedWidget实现Provider。 当然,没有什么能阻止这种类型的实现。

    4.2K90

    StatefulWidget的使用案例

    在Flutter中,自定义组件其实就是一个类,这个类继承自StatelessWidget/StatefulWidget。 StatelessWidget是无状态组件,状态不可变的Widget。...首先我们在VSCode中安装一个名为“Awesome Flutter Snippets”的插件,该插件提供了Flutter中各种常用的类和方法的快速构建方式,可以极大地提升开发效率,如下所示: 捷径...reassemble 重新安装 在调试期间重新组装应用程序时调用,例如在热重新加载期间。...oriantationBldr 方向生成器 创建一个构建器,允许指定和引用设备的方向 layoutBldr 布局生成器 与Builder窗口小部件类似,只是框架在布局时调用构建器函数并提供父窗口小部件的约束...这是基于与Future交互的最新快照构建的。 nosm 没有这样的方法 访问不存在的方法或属性时,将调用此方法。

    3.3K20

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

    关于Provider的源码,如果对设计模式或面向接口编程不熟悉的话,看起来是相当懵逼的,基本就是:懵逼树上懵逼果,懵逼树下你和我;Provider源码使用了大量的抽象类,调用父类构造函数,继承实现断言,...[img] 不管你用或不用Provider,我相信在你读完本文的刷新机制栏目,大概率会对该框架中闪耀的智慧,感到由衷的赞叹!...使用 老规矩,说原理之前,先来看下使用 Provider的使用,和我前俩篇写的Handler和ThreadLocal使用有一些区别 Provider是一个状态管理框架,写它的使用可能会占较多篇幅,所以文章整体篇幅也会较长...Provider.of(context, listen: false)中的context,必须是ChangeNotifierProvider或其子Widget的 使用ProEasyCounterPage..., ); } } _InheritedProviderScope 这里是继承了InheritedWidget,里面重写createElement方法,在构建Widget的时候,这个方法是肯定会被调用的

    1.5K61

    【 源码之间 - Flutter 】 FutureBuilder 使用

    FutureBuilder的使用 先定义异步任务和当前页码,在使用FutureBuilder进行构造组件。全代码见文尾。...,也就是源码中的这里 可以看出回调中会将异步返回的数据放在_snapshot这个瓶子里,并setState 这样_snapshot更新后,会重新执行build方法,又会回调外界的_builderList...父组件刷新时的_FutureBuilderState的行为 在点击加号时,更新异步方法,获取下一页数据,然后父组件执行setState void _doAdd() { setState(() {...说白了就是在封装一下异步任务执行情况,本质也是靠setState进行更新子组件。 ---- 尾声 欢迎Star和关注FlutterUnit 的发展,让我们一起携手,成为Unit一员。...另外本人有一个Flutter微信交流群,欢迎小伙伴加入,共同探讨Flutter的问题,期待与你的交流与切磋。

    1.1K20
    领券