单订阅Stream这种类型的Stream只允许在该Stream的整个生命周期内使用单个监听器。即使在第一个订阅被取消后,也无法在此类流上收听两次。...StreamBuilder监听Stream,每当某些数据输出Stream时,它会自动重建,调用其builder回调。...下面的代码演示了如何使用StreamBuilder: StreamBuilder( key: ...optional, the unique ID of this Widget......重建并“刷新”计数器; 我们不再需要State的概念,所有内容都通过Stream接收; 这是一个很大的改进,因为调用setState()方法会强制整个Widget(和任何子窗口小部件)重建。...在这里,只重建StreamBuilder(当然还有子窗口小部件); 我们仍然在为页面使用StatefulWidget的唯一原因,仅仅是因为我们需要通过dispose方法释放StreamController
它需要一个 child 的挂件,这个挂件通常是可滚动的挂件,和一个 onRefresh 回调函数来定义当用户触发刷新后发生什么事情。...很重要的一点是,这个函数返回 Future 来保持刷新指示器可见,直到新数据被下载且页面被更新。...比如,如果我们使用简单的 statefule 挂件,我们通过调用 setState 用新数据来重建 rebuild 我们的 widget tree。...当实现下拉刷新,我们经常需要 BuildContext 来触发状态的更改或者在刷新后导航到不同的屏幕。 比如,当新数据被抓取并且页面被更新,我们可能想展示一个成功信息的 SnackBar。...这意味着从一个资源拉取新数据,该资源可能是一个本地数据库或者一个远程服务器,并确保正确刷新指示器逻辑以反映数据获取过程的状态。
实例 实现的效果如下: [App截图] 网络层 请求就是使用官方的http库发起,具体可以看源码。 知乎日报的API网上一搜即可,本文不再赘述。...注释(4)(5)这两个方法是网络请求,分别实现了刷新和加载下一页的逻辑。可以看到,这里请求回来后,做的就是把结果add到inStoryListController这个Sink对象中。...,在stream参数给上我们ViewModel的output stream,也就是说当ViewModel中的Sink对象被add数据后,StreamBuilder会监听到这个变化,然后重新通过builder...注释(2)处,这里是获取到数据后,构建随之更新widget的方法。snapshot.data就是监听的数据,更新后的新数据。...注释(3)处,RefreshIndicator是一个下拉刷新的widget,onRefresh方法里调用了刷新方法。
如图,是StreamBuilder使用基本结构,StreamBuidler基于dart中的异步核心之一Stream,采取观察者模式,发送方通过StreamControll发送数据,观察对象接收到数据后构建自己的内容...在key1的点击事件中往Stream中add数据,这样在key1的流上产生了一条数据,对应的监听者收到数据后,只更新自己的内容,不会重建其他区域。 ? ? ?...StreamBuilder可以完美解决局部刷新的问题,但StreamBuilder也有着同样明显的缺点,使用起来非常麻烦,需要自己手动创建流,将控件用StreamBuilder包裹构造。...对于这条DataLine,最核心的有两个方法 1、添加观察者(通过StreamBuilder包裹实际展示的contentWidget) : 类似数据线连接手机 2、发送数据 :类似通过数据线给手机充电...进行了封装,以此简化StreamBuilder的使用。
,你可以随时随地给它添加subscription,只要新的监听开始工作流,它就能收到新的事件。...####3.2 当数据流变化时,可以刷新小部件。 Stream是一种订阅者模式,当数据发生变化时,通知订阅者发生改变,重新构建小部件,刷新UI。 ###4.如何使用streamBuild?...的监听,StreamBuilder重建并刷新counter //步骤4.往StreamBuilder里添加流,数据变了,就用通知小部件 _streamController.sink.add...问题1 为何选择使用streamBuild 1.方法一使用StatefulWidget,刷新时使用setstate(){},使用setstate(){}刷新,会将整个item 进行重新构建,整个item...仅仅只有“关注”需要改变,其它控件都刷新,会造成资源浪费。
) 支持指示器位置设置,结合监听器可以放置在任意位置 支持页面启动时刷新,并可自定义视图 支持安全区域,不会遮挡内容 可自定义滚动参数,允许列表具有不同的滚动反馈和惯性 3、在线演示 https://xuelongqy.github.io...const FooterLocator.sliver(), ], ), ); 4、使用指示器 EasyRefreshController _controller = EasyRefreshController...await Future.delayed(Duration(seconds: 2)); }, child: ListView.builder( itemCount...refreshOnStart: true, // 刷新完成后重置刷新状态 resetAfterRefresh: true, // 同时触发刷新和加载的回调函数...onRefresh: _refresh, onLoad: _loadMore, childBuilder: (context, physics) { return ListView.builder
为简单起见,此流程由三种可能的状态组成: 图上的状态可以由如下状态机表示,其中包括加载状态和认证状态: 当登录的请求正在进行中,我们会禁用登录按钮并展示进度指示器。...StreamController 添加一个 SignInBloc,用于处理加载状态。...通过 StreamBuilder 来检查加载状态,并使用它来设置登录按钮。...如果在简单值更改时需要重建 widget,请使用 ValueNotifier。 如果你想在 notifyListeners() 调用时有更多掌控,请使用 ChangeNotifier。...总结如下: StatefulWidget 在 state 被删除后,不再记住自己的 state。 使用 Provider,我们可以选择在哪里存储 widget 树中的状态。
严格来说,Notification并不是一个跨Widget数据管理方案,它只完成了一半的功能,即Notification实现了数据状态修改的通知,但是需要监听的Widget收到通知后的处理,还是需要自己来实现的...,这个实现,简单的说,可以是setState来重建UI,复杂了说,可以是配合其它任何一种数据管理/刷新的方案。...'), Expanded( child: StreamBuilder( initialData: '', stream...), Expanded( child: NotificationListener( child: ListView.builder...继承Notification后,直接使用dispatch函数即可实现Notification的分发。
,主要是确保空值不会传递给任何子组件,而且FutureProvider有一个初始值,子组件可以使用该Future值并告诉子组件使用新的值来进行重建。...注意: FutureProvider只会重建一次 默认显示初始值 然后显示Future值 最后不会再次重建 第一步:创建模型 这里和Provider不同的是增加了构造函数,以及changeName变成了...Future,我们模拟网络请求延迟两秒后改变其值。...StreamProvider StreamProvider提供流值,是围绕StreamBuilder,所提供的值会在传入的时候替换掉新值。...0; // 添加书籍 void addFaves(Book book) { _bookIds!.
进入这里 **wait()**函数 等待多个异步任务执行完成后,再调用then() **delayed()**函数 延迟任务执行 ⚠️: Future没有执行完成(有任务需要执行),那么then会直接被添加到...Future的函数执行体后; 如果Future执行完后就then,该then的函数体被放到如微任务队列,当前Future执行完后执行微任务队列 如果Future世链式调用,意味着then未执行完,下一个...它是一个异步流,我们可以在代码中任何地方定义 Stream,然后在其他地方添加数据,Stream会监听到数据变化,并将改变后的数据传递给监听者。...使用 StreamBuilder是Flutter中的一个Widget,记录着流中最新的数据,当数据流发生变化时,会自动调用Builder进行重建 const StreamBuilder({ Key...= null), super(key: key, stream: stream); 可以看到StreamBuilder需要接受一个Stream 使用StreamController 结合
大家也可以使用adb命令对设备进行录屏:adb shell screenrecord /sdcard/test.mp4,再转换为 gif 文件,推荐使用https://ezgif.com/video-to-gif...RefreshIndicator( onRefresh: _onRefresh, //下拉刷新回调 displacement: 10, //指示器显示时距顶部位置..., //指示器背景颜色,默认ThemeData.canvasColor notificationPredicate: defaultScrollNotificationPredicate...fontSize: 15, color: Colors.black38, fontWeight: FontWeight.bold), ), ) : ListView.builder...= null) { _pageCount = -1; //使用自定义方法加载数据,除第一次加载数据后则无需pageCount。
现在我们已经完成了基础框架,我们可以添加一个dropdown,这将允许我们通过价格或名称来过滤产品。为此,我们将使用DropDownButton。...Text('Error: $err'), data: (config) { return Text(config.host); }, ); } 这将在Future完成后自动重建...特别是,你可能认为Flutter的StreamBuilder也能很好地用于监听Stream,但这是一个错误。 使用StreamProvider而不是StreamBuilder有许多好处。...的需要 它缓存了stream所发出的最新值,确保如果在事件发出后添加了监听器,监听器仍然可以立即访问最新的事件 它允许在测试中通过覆盖StreamProvider的方式来mock stream ChangeNotifierProvider...例如,如果你的状态是可变的,使用provider.select来优化Widget的重建可能就会失效,因为select会认为值没有变化。 因此,使用不可变的数据结构有时会更快。
对应的可滚动组件 SliverList 列表 ListView SliverFixedExtentList 高度固定的列表 指定itemExtent的ListView SliverAnimatedList 添加...Flutter官方文档中提到,ListView的默认构造器建议在需要展示的元素个数较少时使用,在展示的元素数量较多时,建议使用ListView.builder() 方法构造视图。...深入查看ListView的源码后可以发现,在默认构造器中使用了SliverChildListDelegate类创建了一个成员变量,而在构造方法中传入的children即作为创建该对象的入参。...false; @override void initState() { super.initState(); // 类初始化时,向ScrollController添加监听...this.indicatorPadding = EdgeInsets.zero, //指示器padding this.indicator, // 指示器 this.indicatorSize
这个模式是为了部署给最终的用户使用。...通过这部分基础了解渲染流程以及主要耗时花费 flutter视图树包含了三颗树:Widget、Element、RenderObject ·Widget: 存放渲染内容、它只是一个配置数据结构,创建是非常轻量的,在页面刷新的过程中随时会重建...另外还有一些debug调试工具可以辅助查看更多信息,注意,只能在debug模式下使用分析,拿到的数据不能作为性能标准 debugProfileBuildsEnabled:向 Timeline 事件中添加每个....减少build中逻辑处理,因为widget在页面刷新的过程中随时会通过build重建,build调用频繁,我们应该只处理跟UI相关的逻辑 2.减少saveLayer(ShaderMask、ColorFilter...,之外的部分剔除掉,所以这也是个耗时操作 3.减少Opacity Widget 使用,尤其是在动画中,因为他会导致widget每一帧都会被重建,可以用 AnimatedOpacity 或 FadeInImage
在BLoC模式下,Widget与Data彻底解耦: App的业务逻辑处理都在BLoC中 Widget通过Sink向BLoC发送数据 BLoC通过Stream通知Widget重建UI 这其实有点类似MVP...记录点击数 点击后增加点击数 所以创建的BLoC类,只对外暴露这两个业务,即对外的Stream和increment函数。...在UI层中,有两种写法,一种是直接使用StatelessWidget,在build函数中初始化BlocProvider.of(context),另一种是使用StatefulWidget...举个例子,比如在第一个界面在流中添加了一些数据,再打开第二个界面的时候,创建StreamBuilder之后,是无法直接获取流的最新数据的,因为这时候流中的的数据在StreamBuilder监听之前就已经结束了...所以这种情况下,要么是在创建StreamBuilder前,初始化initialData的值为流中最新的数据;要么是使用RxDart来强化流的功能。
因为没使用Provider.of(context, listen: true) 向 InheritedElement 添加子Element,所以是刷新了个寂寞!...前置知识 想弄懂Bloc原理,需要先了解下Stream的相关知识 StreamController、StreamBuilder:这俩者的搭配也可以轻松的实现刷新局部Widget,来看下使用 view:Stream...,会发现有几个很麻烦的地方 需要创建Stream的一系列对象 Stream流必须要有关闭操作,所以要使用StatefulWidget StreamBuilder需要写三个参数,很麻烦 Bloc作者借住Provider...transitionFn的逻辑是:将Event参数传入mapEventToState中,然后mapEventToState回传State对象 然后触发listen回调,listen中,将state传emit中,然后触发刷新控件重建...通过setState重建StatefulWidget,以达到局部刷新的效果 手搓一个状态管理框架 Bloc的原理相对Provider而言,要简单很多。。。
一旦 await 的网络请求完成,通过调用 setState() 来更新 UI,这会触发 widget 子树的重建,并更新相关数据。...要使用 http 包,在 pubspec.yaml 中添加如下依赖: dependencies: ......一旦获得结果后,你可以通过调用setState来告诉Flutter更新其状态,setState将使用网络调用的结果更新UI。...如何为长时间运行的任务添加一个进度指示器? 在 iOS 中,在后台运行耗时任务时我们通常会使用 UIProgressView。...在任务开始时,告诉 Flutter 更新状态,并在结束后隐藏。 在下面的例子中,build 函数被拆分成三个函数。
此版本还提供了一个相当大的应用程序大小的改善是由于几个 补丁 是 添加 了一个大的结果。...请注意,TextStyles所谓的body1和body2在材料设计规范被称为bodyText1和bodyText2颤振的TextThemeAPI。...如果未在Dart DevTools的预发行版中看到“网络”选项卡(例如,如果从命令行运行它),则可以使用以下命令手动更新它: $ pub globalactivate devtools 按下“记录”按钮后...在上一个版本中,Flutter团队弃用了原始的Android支持库,并将其移至AndroidX作为所有新项目的默认设置。...进行此更改后,分析错误不足以阻止Hot Reload正常运行,而取决于VM的编译器错误。
= color; } } 复制代码 ---- 2.案例调试测试 现在只在 ShapePainter#paint 方法上添加断点, 下面是两次 paint 时的情况。...这时可以使用 repaint 属性来控制画板的刷新,做到在画板对象保存不变的情况下,刷新画板,其原理也在第三篇说过了。...当认识到 ValueListenableBuilder 、FutureBuilder、StreamBuilder、AnimatedBuilder 这些组件的局部刷新,或者 Provider、Bloc 这样的状态管理提高的局部刷新组件...所以 State#setState 的好与坏取决于 Element 的层级,如果有人非要在高层级使用 State#setState 来刷新,说 State#setState 不好,就相当于残害无辜后说这把刀是恶刀一样...---- StreamBuilder 组件根据 Stream 的状态,使用 setState 进行重新构建的。 ?
但一个程序只有不可变的配置是不行的,我们不可能编写一个只绘制一次后就停止的应用。...但就这样改变你会发现 ui 是不会刷新的,因为在 StatefulWidget,如果你想改变某个值,同时要同步更新 ui,需要使用 setState 方法。...所以现在再回过去看 ui,会发现 ui 已经刷新了。 以上是使用 StatefulWidget 来达到 ui 的动态改变。再对比于之前的 StatelessWidget,它们之间的区别显而易见了。...由于是同一种类型 Container,将会直接被替换,同时使用更新后的 item.unread,所以对应的 Container 的 color 也将发生改变。最终呈现的是布局的刷新。...使用 dart 语言进行开发,项目架构是基于 Model/State/ViewModel 的 MSVM;使用 Navigator 进行页面的跳转;网络框架使用了 dio。
领取专属 10元无门槛券
手把手带您无忧上云