扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
前几天做一个功能,需要在异步回调未完成时候进行等待;也就是说同步执行N个异步方法. 总是在第一个异步未执行完成时候剧执行了第二个异步方法,效果很不理想.有什么方法可以实现这样的功能呢?
创新互联专注于东坡企业网站建设,自适应网站建设,成都商城网站开发。东坡网站建设公司,为东坡等地区提供建站服务。全流程按需制作网站,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务
大体的思路:给每个异步加上等待;如下:
但是registerPayListen方法怎么才能在我不想要结束时候等待呢?
此处我是采用定时器去监听某一个bool当为真时候则结束异步;如下:
只有在 completer.complete();执行时候才会回调异步方法并进行回调
本文首发在公众号 Flutter那些事 ,欢迎大家多多关注。
工具安装:
Flutter基础篇:
Flutter进阶篇:
Dart语法基础篇:
Dart语法进阶篇:
说明:本文中的所有函数的引用在 main 函数中:
这里的执行结果是:
Futue直接new就可以了。我这里没有具体的返回数据,所以就用匿名函数代替了, Future future = new Future(() = null); 相当于 FutureNull future = new Future(() = null); 泛型如果为null可以省略不写,为了便于维护和管理,开发中建议加上泛型。
输出结果是:
future里面有几个函数:
then :异步操作逻辑在这里写。
whenComplete :异步完成时的回调。
catchError :捕获异常或者异步出错时的回调。
因为这里面的异步操作过程中没有遇到什么错误,所以catchError回调不会调用。
我们可以看到执行结果是:
我们可以看到输出结果是: 2 1 3 和我们创建Future对象的先后顺序完全一致。
我们可以看到结果为 1 2 3 ,和我们调用then的先后顺序无关。:
当then回调函数里面还有then回调的时候,这时候的流程跟前面就不太一样了,也是一个大坑,也是面试经常会被问到的一个知识点。
我们可以看到执行结果如下:
结果还是一样的:
运行结果是:
这里再次证明了上面我的猜想: 执行顺序和和创建Future的先后顺序有关,如果有多个then嵌套执行,先执行外面的then,然后执行里面的then。
执行结果如下,我们可以看到then内部创建的Future要等到then执行完了,最后再去执行的:
根据上文总结的特点,我们可以不用运行也能推断出输出结果:
为了验证我们的猜想,我们打印一下输出结果,果然我们的证明是正确的。
我们重点看看 then函数的文档说明:
then 注册在 Future 完成时调用的回调。
当这个 Future 用一个 value 完成时,将使用该值调用 onValue 回调。
如果 Future 已经完成,则不会立即调用回调,而是将在稍后的 microtask(微任务) 中调度。
如果回调返回 Future ,那么 then 返回的 future 将与 callback 返回的 future 结果相同。
onError 回调必须接受一个参数或两个参数,后者是[StackTrace]。
如果 onError 接受两个参数,则使用错误和堆栈跟踪时调用它,否则仅使用错误对象时候调用它。
onError 回调必须返回一个可用于完成返回的future的值或future,因此它必须是可赋值给 FutureOr R 的东西。
返回一个新的 Future ,该 Future 是通过调用 onValue (如果这个Future是通过一个value完成的)或' onError (如果这个Future是通过一个error完成的)的结果完成的。
如果调用的回调抛出异常,返回的 future 将使用抛出的错误和错误的堆栈跟踪完成。在 onError 的情况下,如果抛出的异常与 onError 的错误参数“相同(identical)”,则视为重新抛出,并使用原始堆栈跟踪替代
如果回调返回 Future ,则 then 返回的 Future 将以与回调返回的 Future 相同的结果完成。
如果未给出 onError ,并且后续程序走了刚出现了错误,则错误将直接转发给返回的 Future 。
在大多数情况下,单独使用 catchError 更可读,可能使用 test 参数,而不是在单个 then 调用中同时处理 value 和 error 。
请注意,在添加监听器(listener)之前, future 不会延迟报告错误。如果第一个 then 或 catchError 调用在 future 完成后发生 error ,那么 error 将报告为未处理的错误。
Flutter中有两个常用的状态Widget分为StatefulWidget和StatelessWidget,分别为动态视图和静态视图,视图的更新需要调用StatefulWidget的setState方法,这会遍历调用子Widget的build方法。如果一个页面内容比较复杂时,会包含多个widget,如果直接调用setState,会遍历所有子Widget的build,这样会造成很多不必要的开销,所以非常有必要了解Flutter中局部刷新的方式:
globalkey唯一定义了某个element,它使你能够访问与element相关联的其他对象,例如buildContext、state等。应用场景:跨widget访问状态。
例如:可以通过key.currentState拿到它的状态对象,然后就可以调用其中的onPressed方法。
Flutter框架内部提供了一个非常小巧精致的组件,专门用于局部组件的刷新。适用于值改动的刷新。
实现原理:在 initState 中对传入的可监听对象进行监听,执行 _valueChanged 方法,_valueChanged 中进行了 setState 来触发当前状态的刷新。触发 build 方法,从而触发 widget.builder 回调,这样就实现了局部刷新。可以看到这里回调的 child 是组件传入的 child,所以直接使用,这就是对 child 的优化的根源。
可以看到 ValueListenableBuilder 实现局部刷新的本质,也是进行组件的抽离,让组件状态的改变框定在状态内部,并通过 builder 回调控制局部刷新,暴露给用户使用。
通过这个可以创建一个支持局部刷新的widget树,比如你可以在StatelessWidget里面刷新某个布局,但是不需要改变成StatefulWidget;也可以在StatefulWidget中使用做部分刷新而不需要刷新整个页面,这个刷新是不会调用Widget build(BuildContext context)刷新整个布局树的。
异步UI更新:
很多时候我们会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中显示一个加载框,等获取到数据时我们再渲染页面;又比如我们想展示Stream(比如文件流、互联网数据接收流)的进度。当然StatefulWidget我们完全可以实现以上功能。但由于在实际开发中依赖异步数据更新UI的这种场景非常常见,并且当StatefulWidget中控件树较大时,更新一个属性导致整个树重建,消耗性能,因此Flutter专门提供了FutureBuilder和SteamBuilder两个组件来快速实现这种功能。
通常情况下,子Widget无法单独感知父Widget的变化,当父state变化时,通过其build重建所有子widget;
InheriteddWidget可以避免这种全局创建,实现局部子Widget更新。InheritedWidget提供了一种在Widget树中从上到下传递、共享数据的方式。Flutter SDK正是通过InheritedWidget来共享应用主题和Locale等信息。
InheritedWidgetData
TestData
InheritedTest1Page
provider是Google I/O 2019大会上宣布的现在官方推荐的管理方式,而ChangeNotifierProvider可以说是Provider的一种:
yaml文件需要引入provider: ^3.1.0
顶层嵌套ChangeNotifierProvider
创建共享数据类DataInfo:
数据类需要with ChangeNotifier 以使用 notifyListeners()函数通知监听者更新界面。
使用Provider.of(context)获取DataInfo
nextPage:
使用Consumer包住需要使用共享数据的Widget
RepaintBoundary就是重绘边界,用于重绘时独立于父视图。页面需要更新的页面结构可以用 RepaintBoundary组件嵌套,flutter 会将包含的组件独立出一层"画布",去绘制。官方很多组件 外层也包了层 RepaintBoundary 标签。如果你的自定义view比较复杂,应该尽可能的避免重绘。
以上总结了几种Flutter的局部刷新的方式,可根据实际需要使用不同的方式,最适合的才是最好的。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流