Flutter的Don't use BuildContext's across async gaps警告解决方法

问题

Flutter开发中遇到Don't use BuildContext's across async gaps警告

有问题的源码

问题原因

“不要在异步间隙(async gaps)中使用 BuildContext” 是一个Flutter中的常见警告消息,通常表示你正在尝试在异步操作中访问 BuildContext,这是一个不推荐的做法,因为它可能引发不确定的行为或错误。

如果在将上下文传递给AlertDialog后导航堆栈发生更改,并且尝试使用旧上下文再次导航,则会出现错误。

问题分析

Context的含义

Flutter中的 BuildContext 和 Context 是相同的,BuildContext 是 Context 的别名。这两个术语用来表示小部件树中的位置信息和上下文环境,用于在构建小部件树和访问资源(例如主题、本地化、导航等)时提供上下文信息。

在Flutter中,BuildContext 或 Context 表示的是一个由小部件树组成的层次结构中的位置。每个小部件都有一个与之相关的 BuildContext,这个上下文包含有关小部件的信息,例如其位置、父级小部件、主题数据等等。

尽管 Context 和 BuildContext 是相同的类型,但通常我们更倾向于使用 BuildContext 这个术语,因为它更明确地表示它是与构建过程相关的上下文。

BuildContext的作用

BuildContext 类型通常用于以下操作:

  • 访问父级小部件:你可以使用 BuildContext 访问小部件树中的父级小部件,这对于在小部件之间传递数据和状态非常有用。
  • 获取主题数据:通过 BuildContext 可以访问当前主题的数据,如颜色、字体、间距等。
  • 获取本地化信息:你可以使用 BuildContext 获取本地化信息,以根据用户的语言偏好来显示文本。
  • 导航:BuildContext 通常用于导航操作,如推送新路由或弹出对话框。
  • 构建小部件:BuildContext 是在小部件的 build 方法中传递的,它告诉小部件在小部件树中的位置。

BuildContext 和 Context 都代表了小部件树中的位置和上下文信息,它们在构建和交互中扮演着关键的角色,但它们实际上是相同的概念的不同表达方式。因此,你可以放心地将它们视为等同的,使用其中一个作为标识符,以便更清晰地表示其作用。

特殊情况

然而,在某些情况下,你可能需要在异步操作中访问 BuildContext,例如在异步回调中执行 UI 操作。这通常是不安全的,因为异步操作可能会在 BuildContext 不再有效的情况下执行,从而引发错误。

解决方法


使用

不要在异步间隙中直接使用 BuildContext,因为它可能会导致不安全的操作。使用提供的方法来安全地查找小部件并在异步操作中访问它们的上下文。这可以帮助你避免潜在的问题和错误。

官方说明如下:

Details

DON’T use BuildContext across asynchronous gaps.

Storing BuildContext for later usage can easily lead to difficult to diagnose crashes. Asynchronous gaps are implicitly storing BuildContext and are some of the easiest to overlook when writing code.

When a BuildContext is used, its mounted property must be checked after an asynchronous gap.

BAD:

GOOD:

GOOD:

参考链接


性能有坑 | 慎用 Java 8 ConcurrentHashMap 的 computeIfAbsent

前言

我们先看一段代码,代码中使用 Map 的时候,有可能会这么写:

Java 8 的 java.util.Map 里面有个方法 computeIfAbsent,能够简化以上代码:

以上这种写法除了简洁,如果使用的是 java.util.concurrent.ConcurrentHashMap,还能够在并发调用的情况下确保 calculateValue 方法不会被重复调用,保证原子性。

不过,前段时间对 Apache ShardingSphere-Proxy 做压测时遇到一个问题,当 BenchmarkSQL 连接 ShardingSphere Proxy 的 Terminal 数量比较高时,其中一条很简单的插入 SQL 执行延迟增加了很多。借助 Async Profiler 发现 Java 8 ConcurrentHashMap 的 computeIfAbsent 在性能上有坑。

不了解 Apache ShardingSphere 的读者可以参考 https://github.com/apache/shardingsphere

继续阅读性能有坑 | 慎用 Java 8 ConcurrentHashMap 的 computeIfAbsent

解决Windows 10备份和还原遇到的0x80070544问题

随着主力计算机设备年限越来越近,对数据保护的重视度也越来越高,尤其之前遭遇过数据损失。目前采用的备份方案是使用文件历史记录功能对 OneDrive 等经常会访问和编辑的目录进行备份。对于其他归档用途的目录则使用备份和还原功能,定期执行一次备份。而备份的位置建议是额外的磁盘或 NAS 提供的 iSCSI,gOxiA 为了图方便和节省 NAS 空间,则使用的是共享文件夹的方式。在实际配置过程中如果使用共享文件夹这样的网络位置,则可能会遇到 0x80070544 故障问题,提示为“请求的验证信息类无效”。

继续阅读解决Windows 10备份和还原遇到的0x80070544问题

Android:Installed Build Tools revision 33.0.2 is corrupted.

使用33.0.2及以上版本的build-tools编译Android应用时。

有些人会按照提示去SDK Manager中重新安装build tools,然后发现这样做是无用的

编译时会收到:

Windows:

Linux/macOS:

解决方案:

更改批处理文件名称

Windows系统:

  1. 找到build tools目录中的d8.bat,将文件名修改为dx.bat。
  2. 找到build tools目录中的lib/d8.jar,将文件名修改为dx.jar。
  3. 回到Android Studio重新打包。

Linux/macOS系统:

  1. 找到build tools目录中的d8,创建软链接 ln -s d8 dx
  2. 找到build tools目录中的lib/d8.jar,创建软链接 ln -s d8.jar dx.jar
  3. 回到Android Studio重新打包。

参考链接


Android:Installed Build Tools revision 33.0.2 is corrupted.

使用UrlQuerySanitizer来处理URL

网上对于 UrlQuerySanitizer 的资料比较少,这个是 Android 提供的一个用来处理 url 的 API。由于项目的需要,需要对 url 的 query 参数进行排序,因此需要解析 url 并处理 query 参数。

最初的方法是使用 Uri:

通过这样的方式就可以解析 url,并获取到各个 query 参数。但后来发现 Uri 不能处理一些特殊字符,比如#,Uri 会截断#以后的内容,这样就不能满足开发需求。经过各种 google,最后发现了一个 UrlQuerySanitizer 的 API:

首先要使用 setAllowUnregisteredParamaters 让其支持特殊字符,然后使用 setUnregisteredParameterValueSanitizer 来设置支持哪些特殊字符,UrlQuerySanitizer 提供了集中默认的 ValueSanitizer:

每种 ValueSanitizer 都对应过滤哪些字符,被过滤掉的特殊字符会被替换成_或者空格。
如果默认的 ValueSanitizer 不能满足开发需求,还可以自己构造 ValueSanitizer:

UrlQuerySanitizer 也可以通过 key 来获取相应的 value,比如给一个 url:http://coolerfall.com?name=vincent:

UrlQuerySanitizer 还可以只解析 query 参数,比如:name=vincent&article=first:

以上就是 UrlQuerySanitizer 大致用法,用来解析处理 url 非常的方便。

参考链接


使用 UrlQuerySanitizer 来处理 url

macOS Sonoma(14.2.1)通过UTM虚拟机编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

前置条件


根据 Google 官方文档,2021年6月22日之后的Android系统版本不支持在macOS系统上构建,我们在 Applic SiliconmacOS 系统是不能直接成功构建后续版本的,但是之前的版本可以在修改编译配置后成功编译,只是是否能正常运行存疑

尝试过使用 Podman Desktop / Docker 方式进行编译、也尝试过借助 OrbStackLima 这些纯虚拟机通过安装 ubuntu 22.04 系统镜像的方式进行编译,结果都在执行 lunch 命令的时候长时间卡住,观察系统进程发现名为 nsjail 进程的 CPU 占用持续卡住在 100% 上无法继续编译,并且由于 Docker 或者虚拟机文件系统是 Linux 文件系统,而宿主机的文件系统是 AppleFS 文件系统,导致需要进行文件转换,中间的转换性能代价非常高,性能很差。

相反,目前测试来看,直接在 UTM 虚拟机里执行编译的性能反倒更好一些。

目前测试发现存在严重的文件系统缺陷,编译/大量文件复制过程中,经常出现文件系统损坏,导致编译失败。

原因参考:

https://github.com/utmapp/UTM/pull/5869
https://github.com/utmapp/UTM/pull/5919

需要等待 UTM 合并到主分支。

另外,我们需要安装 Rosetta 2 支持运行部分 x86_64 应用。注意  Rosetta 2 只支持 64 位应用,不支持 32 位应用。 参考 Does Rosetta 2 support 32-bit Intel apps?

继续阅读macOS Sonoma(14.2.1)通过UTM虚拟机编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

ubuntu 22.04.3使用blivet-gui创建SoftwareRAID

最近家里安装降噪棉的时候使用了钉书钉,结果安装的时候,意外震坏了一块八年历史的老西数硬盘,造成数据丢失。

话说,西部数据的硬盘耐用性真的很成问题,家里至少已经坏了五块硬盘了,四块都是西部数据的。

于是另购了一块希捷的银河系列 16TB 硬盘,打算跟现存的一个刚刚替换的西部数据的 12TB 红盘(质保期之内坏了,走售后,花了一个多月换了一张盘,估计寿命也是堪忧),组一个 Raid 1 软阵列,到时候万一再有硬盘损坏,至少可以保住数据。

当前设备是使用 HP Gen8 上安装的 ubuntu 22.04.3 系统,四个盘位,其中两个从群晖上替换下来的 4TB 硬盘直接挂载到两个盘位上,依旧保持群晖的 Raid 1 软阵列。另外两个盘位,就是我们需要新组的软件 Raid 1 的位置了。

网上搜索了半天,都是需要通过命令行,逐个磁盘分区,分区之后再使用 mdadm 通过命令行组建阵列,虽然难度不大,但是操作比较繁琐,还是希望能在 UI 界面上点击一下鼠标搞定。

可以使用 storaged-project/blivet-gui 这个开源项目完成这个需求。

继续阅读ubuntu 22.04.3使用blivet-gui创建SoftwareRAID

QUIC 开源实现列表

QUIC的全称是 Quick UDP Internet Connections protocol,由 Google 设计提出,目前由 IETF 工作组推动进展,其设计的目标是替代 TCP 成为 HTTP/3 的数据传输层协议。本文章整理目前各大厂及主流编程语言的开源 QUIC 实现。

在线社区:discord/quic

维护者:YoMo

C/C++

Name Version Roles Handshake GitHub
Microsoft's MsQuic draft-29/v1 client, server TLS 1.3 RFC github.com/microsoft/ms
Facebook's mvfst draft-29 library, client, server TLS 1.3 github.com/facebookincu
Google's Chromium Q043, Q046, Q050, T050, T051, draft-27, draft-29 library, client, server QUIC Crypto, TLS chromium.org/quic/playi
ats (Apache Traffic Server) draft-29 client. server TLS 1.3 cwiki.apache.org/conflu
LiteSpeed's lsquic v1, Draft-34, Draft-29, Draft-27, Q043, Q046, and Q050 library, client, server QUIC Crypto, RFC 8446 github.com/litespeedtec
ngtcp2 draft-29, draft-30, draft-31, and draft-32 library, client, server TLSv1.3 (RFC 8446) github.com/ngtcp2/ngtcp
Cloudflare's nginx-cloudflare draft-27, draft-28, draft-29 server TLSv1.3 (RFC8446) github.com/cloudflare/q
picoquic draft-32/31/30/29/28/27 library and test tools, test client, test server TLS 1.3 (using picotls) github.com/private-octo
Pluginized QUIC draft-29 library, client, server TLS 1.3 (using picotls) github.com/p-quic/pquic
quant draft-33, draft-34, v1 library, client, server TLS 1.3 github.com/NTAP/quant
Fastly's quicly draft-27 client, server TLS 1.3 (final) github.com/h2o/quicly
nginx-quic draft-27 .. draft-32 server TLSv1.3 (RFC8446) hg.nginx.org/nginx-quic
XQUIC draft-29,v1 client, server TLS 1.3 github.com/alibaba/xqui

Rust

Name Version Roles Handshake GitHub
Cloudflare's quiche draft-27, draft-28, draft-29 library, client, server TLSv1.3 (RFC8446) github.com/cloudflare/q
Mozilla/Firefox's Neqo draft-27 through version 1 library, client, server TLS 1.3 github.com/mozilla/neqo
Quinn draft-28 library, client, server TLS 1.3 github.com/djc/quinn

Go

Name Version Roles Handshake GitHub
quic-go always the current draft library, client, server TLS 1.3 RFC github.com/lucas-clemen

Java

Name Version Roles Handshake GitHub
kwik draft-29, draft-30, draft-31, draft-32 library, client TLS 1.3 bitbucket.org/pjtr/kwik

Node.js

Name Version Roles Handshake GitHub
Node.js QUIC draft-25 client, server TLS 1.3 github.com/nodejs/quic
quicker draft-22 client, server TLS 1.3 github.com/rmarx/quicke

Python

Name Version Roles Handshake GitHub
aioquic draft-29 through version 1 library, client, server TLS 1.3 github.com/aiortc/aioqu

Haskell

Name Version Roles Handshake GitHub
Haskell quic draft-29 library, client, server TLS 1.3 github.com/kazu-yamamot

参考链接


QUIC 开源实现列表

云服务器 ECS Linux SSH 客户端断开后保持进程继续运行配置方法

在云服务器 ECS Linux 系统中,通常我们在执行一些运行时间比较长的任务时,必须等待执行完毕才能断开 SSH 连接或关闭客户端软件,否则可能会导致执行中断。

本文介绍几种保障程序在用户退出登录后持续运行的方法。

使用 nohup 执行


nohup 的作用顾名思义,它使得后面的命令不会响应挂断(SIGHUP)信号。也就是说,通过远程登录执行 nohup 后,即使退出登录后,程序还是会正常执行。通常情况下,nohup 命令最后会跟上 & 字符,表示将这个命令放至后台执行,这样才能真正做到将这个命令放至后台持续的执行。

操作示例:
1. 正常的执行命令为 bash hello.sh,执行结果为每秒输出一行的小程序:

2. 在命令头尾分别加上 nohup 和 &,变为 nohup bash hello.sh &,可以看到 nohup 输出了一行信息,再按一下回车键就跳回了 shell 命令行,此时命令已经在后台执行了,nohup 将命令的输出重定向至当前目录的 nohup.out 文件中。同时注意到 nohup 会将对应程序的 PID 输出,PID 可用于需要中断进程时 kill 进程。

3. 通过 tail -f nohup.out 可以持续的查看 nohup.out 的输出,达到监视程序的效果。

4. 在命令中也可以使用重定向将程序的输出改为自己想要的文件名,如 nohup bash hello.sh >hello.log &,则程序的输出就会写到 hello.log 文件中。

5. 若程序不会自动退出,那么此时需要使用 kill 命令来结束进程。比如,可以使用命令 kill -TRM <PID> 来操作,其中 PID 即为之前 nohup 输出的值,在此例中该值为 1231。

使用限制:

nohup 通常用于执行无干预的自动化程序或脚本,无法完成带有交互的操作。

使用 screen 执行


安装 sceen 工具

Linux 系统默认未自带 screen 工具,需要先进行安装:

  • CentOS 系列系统: yum install screen
  • Ubuntu 系列系统: sudo  apt-get  install screen
使用简介

1. 创建 screen 窗口

2. 列出 screen 进程,并进入所需 screen

如下图

然后进行所需操作,比如运行脚本、执行程序等等。

如下图示例:创建ftp连接后台下载传输文件

3. 退出保存

前述 ftp 操作示例开始传输后,在窗口中键入Ctrl+a 键,再按下 d 键,就可以退出 SSH 登录,但不会影响 screen 程序的执行。

4. 保存会话以便继续执行

可以利用 screen 这种功能来管理的远程会话。操作步骤概述:

  • 正常 SSH 登录服务器
  • 创建 screen 窗口
  • 执行所需任务
  • 需要临时中断退出时,Ctrl + a 再按下 Ctrl + d 保存退出
  • 需要继续工作时,再次 SSH 登录服务器,然后直接执行 screen -r -d 恢复会话即可。

参考链接


云服务器 ECS Linux SSH 客户端断开后保持进程继续运行配置方法

Centos 7/RedFlag 7/Asianux 7安装|更新Git

背景描述

Centos 7/RedFlag 7/Asianux 7 上的 Git 版本太陈旧,在使用过程中会遇到问题,比如不支持目录分支(release/v01 这种格式会在检出的时候报错),因此需要升级 Git 版本。

安装依赖包

源代码安装和编译git,需安装一些依赖。

卸载旧版本

安装步骤

验证版本

参考链接