前言

怎么将一个Callback回调转化成Future同步方法(Callback to Future),可以配套async / await去使用呢?

个人觉得,这是一个很常见的现象,不知道为啥,很多人在说明Future用法的时候,都没提到这个场景,奇怪+懵逼,只能自己去苟解决方案了。

实现

不多哔哔,先看实现,赶时间的靓仔,可以直接忽略掉历程描述

  • 记录下Callback to Future的写法,使用Completer类即可
class ViewUtil {
///界面初始化完成
static Future<Void> initFinish() async {
Completer<Void> completer = Completer(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
completer.complete();
}); return completer.future;
}
}
  • 使用

    • 使用起来,瞬间简单很多
void _init() async {
await ViewUtil.initFinish();
///下面可以使用加载弹窗
}

说明

  • Future和Completer的泛型最好保持一致

    • 例如都是String的话,complete()方法里面就可以加上相应的内容,然后await接受这个方法时候,就能拿到complete()方法里面输入的值了
class ViewUtil {
///界面初始化完成
static Future<String> initFinish() async {
Completer<String> completer = Completer(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
completer.complete("测试一下...");
}); return completer.future;
}
} void _init() async {
var s = await ViewUtil.initFinish();
print(s);
}

历程

  • 为什么我要将Callback转成Future方法?

    • 大家知道,Flutter在加载页面的时候,有个渲染的过程,在没渲染完成的时候,你去显示一些View的操作,会报错的,例如:加载loading弹窗
    • 解决方法可能大家都知道,Lifecycle.initState / iniState 生命周期里面做个延时操作或者使用WidgetsBinding
//延时操作
await Future.delayed(Duration(milliseconds: 200));
//下面可以加载弹窗 //使用WidgetsBinding
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
//此处可以加载弹窗
});
  • 当然,使用WidgetsBinding是更靠谱和准确的,但是这个Callback就让我很方了,而且,这名字太长,也不太记的住,这就需要将它封装了
  • 封装WidgetsBinding
    • 蛋筒了,这玩意怎么封装呢
class ViewUtil {
///界面初始化完成
static Future<Void> initFinish() async {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { });
}
}
  • 首先我想到了:Future.delayed()

    • 进去看下他的源码
    • 有戏,可以看到,这里面明显包含了一个Timer中的Callback回调,但最后转换成了,Future方法
factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) {
if (computation == null && !typeAcceptsNull<T>()) {
throw ArgumentError.value(
null, "computation", "The type parameter is not nullable");
}
_Future<T> result = new _Future<T>();
new Timer(duration, () {
if (computation == null) {
result._complete(null as T);
} else {
try {
result._complete(computation());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
}
}
});
return result;
}
  • 分析下

    • 首先是实例化一个_Future()对象,然后返回了这个_Future()对象
    • 可以看到方法的最下方是直接返回这个对象,可想而知,这地方,肯定一直处于一个阻塞状态,在等待一个条件结束这个阻塞状态
    • 然后在Timer的延迟时间到了后,其回调中使用了_complete()这个方法,这个方法应该是结束了_Future()对象的阻塞状态,然后再返回_Future()对象,同时这个方法也结束了
  • 这不就简单了,我把这个抄出来不就欧了

  • 这个_Future类是个私有方法,在future_impl.dart文件,把这个文件拷出来,放在我们工具类文件同一个包下,

    • 然后。。。

  • 这一堆报错,玩毛线啊,肯定是我打开的方式不对

    • 难道要一个一个去解决这些报错?要是这么麻烦,还搞毛线!

  • 是不是我搜索的姿势不对,再来搜搜看

    • 我去,还自动给我提示:dart callback to future,这么神奇的吗?试试看

Flutter&Dart Callback转同步的更多相关文章

  1. [flutter+dart] windows7下开发环境的安装与配置

    前言 博主是做嵌入式的,参加工作时间也不久,而且是非科班出身,之前从未接触过移动开发.最近了解到了flutter框架和dart语言,想作为第二语言学习一下,因此会从最基础的环节开始,以此博客作为记录, ...

  2. Android Gradle Issue - Flutter / Dart

    解决 "Minimum supported Gradle version is 4.6. Current version is 3.3." I have a problem wit ...

  3. Flutter & Dart

    Flutter & Dart https://www.dartlang.org/install https://flutter.dev/ https://flutter.dev/docs/ge ...

  4. 【Flutter 1-2】在 Windows 10下安装Flutter+Dart+Android Studio 配置Flutter开发环境

    在 Windows 10下安装Flutter+Dart+Android Studio 配置Flutter开发环境 文章首发地址 配置环境变量 由于部分网站被墙的原因,我们需要先配置Flutter国内镜 ...

  5. flutter & dart & vs code & bug

    flutter & dart & vs code & bug Waiting for another flutter command to release the startu ...

  6. 函数式编程:Flutter&Dart中的组合

    本文翻译自: Composition in Flutter & Dart 在 Flutter & Dart 中使用组合创建模块化应用程序. 什么是组合? 在dictionary.com ...

  7. flutter shared_preferences 异步变同步

    前言 在开发原生iOS或Native应用时,一般有判断上一次安装的版本和当前版本是否是同一个版本,如果不是同一个版本,则要显示引导页,这个过程是把版本号持久化存储起来,在每一次启动时进行判断,这个过程 ...

  8. Flutter & Dart 安装在window系统

    一.系统环境 flutter最低要求 1,windows7 SP1 64位版本以上,我的系统就是windows 7 sp1 64bit 2,git for windows ,没有安装的需要到这里下载  ...

  9. 将已经存在的异步请求callback转换为同步promise

    由于js是单线程执行,为防止阻塞,会有很多异步回调函数callback,嵌套层次多了,可读性就差了很多.随着社区的发展,出现了promise.我们来将一些常见的回调函数做修改,变成promise的链式 ...

  10. Flutter Dart中的异步

    以下内容从官网得到: https://webdev.dartlang.org/articles/performance/event-loop Even-Looper Dart是单线程模型,也就没有了所 ...

随机推荐

  1. gradle打包命令含离线模式

    gradle打包命令gradlew clean 清理gradlew clean build -x test --refresh-dependencies 离线方式: gradlew --offline ...

  2. k8s使用rbd作为存储

    k8s使用rbd作为存储 如果需要使用rbd作为后端存储的话,需要先安装ceph-common 1. ceph集群创建rbd 需要提前在ceph集群上创建pool,然后创建image [root@ce ...

  3. recastnavigation.Sample_TempObstacles代码注解 - rcBuildHeightfieldLayers

    烘培代码在 rcBuildHeightfieldLayers 本质上是为每个tile生成高度上的不同layer 算法的关键是三层循环: for z 轴循环 for x 轴循环 for 高度span 循 ...

  4. CodeServer 不能粘贴

    CodeServer 在没有SSL证书时, 由一浏览器的限制, 默认是不能粘贴的. 在局域网中, 如果不考虑安全性的话, 可以考虑直接把加密关掉, 就能复制粘贴了. 配置文件如下: cert: Tru ...

  5. USB 协议学习:000-有关概念

    USB 协议学习:000-有关概念 背景 USB作为一种串行接口,应用非常广泛.掌握usb也是作为嵌入式工程师的一项具体要求. 概述 USB( Universal Serial Bus, 通用串行总线 ...

  6. 全志科技T3国产工业核心板规格书(四核ARM Cortex-A7,主频1.2GHz)

    1 核心板简介 创龙科技SOM-TLT3是一款基于全志科技T3处理器设计的4核ARM Cortex-A7国产工业核心板,每核主频高达1.2GHz. 核心板通过邮票孔连接方式引出CSI.TVIN.MIP ...

  7. 【Error】mysql的error.log中ranges: 268 max_threads: 4 split: 268 depth: 2是什么意思?

    2021-12-08T09:36:39.612332+08:00 44213799 [Note] [MY-011825] [InnoDB] Parallel scan: 4 2021-12-08T09 ...

  8. 开源GTKSystem.Windows.Forms框架让C# winform支持跨平台运行

    目录 一.简介 二.GTKSystem.Windows.Forms框架的优势 三.支持界面皮肤主题定制 四.多种控件支持 五.支持Dock.Anchor.SplitContainer布局缩放 六.支持 ...

  9. yb课堂 开发前端项目路由 《三十五》

    Vue-Router开发前端项目路由 vue-router 是Vue.js官方的路由管理器,它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌 官方文档:https://router.vue ...

  10. 开源免费又好用的中式数据报表:UReport2是一款高性能的架构在Spring之上纯Java报表引擎,通过迭代单元格可以实现任意复杂的中国式报表。

    北润乾.南帆软,数加发力在云端. uReport 身何安?中式报表真开源. 报表江湖之中,uReport安身立命的产品品类定位是什么? 说来很简单,uReport的价值在于填补了这样一个市场空白:开源 ...