admin管理员组

文章数量:1566362

作者简介

 

Kui,携程移动端高级软件工程师,专注于移动端开发,热衷于移动端跨平台技术的研究和实践。

一、前言 

距离Flutter正式发布已经3年了,国内各大互联网公司都有相继使用,携程今年也在许多业务中使用了Flutter进行开发。

Trip是一款面向海外用户的App,从年中开始便将卖点页、预定页等页面全量转为Flutter,随之而来的便是代码质量管理的问题。由于篇幅有限,本文将从静态代码检测、空安全、单元测试这几个部分来介绍Trip在Flutter业务迭代中提高代码质量做的一些努力。

二、空安全&静态代码检测

空错误是在开发中出现频率较高且通常很难被发现的一类错误。现在越来越多的语言支持空安全。Dart 自2.12版本之后,也支持了稳定的空安全声明,可以在编译期就避免空错误。

2.1 空安全语法

下面整理了常用的空安全语法。

int? aNullableInt = null; //可空声明
late int lateInt; //延迟声明
int value = a ?? b; //如果a为空则执行b
int value = aNullableInt!; //非空操作符
cat?.mouth.eat(); //如果为空不执行后面的方法
func(String a, {required String b, String? c}){} //必传参数和可空参数
List<String> //包含非空字符串的非空列表
List<String>? //包含非空字符串的可空列表
List<String?> //包含可空字符串的非空列表
List<String?>? //包含可空字符串的可空列表
var map = <String, int?>{'test': 1}; //未指定类型时{}是set类型
Function(String a)? func;
func("2"); // error
func?.call("2"); //ok

2.2 空安全迁移 

由于在Dart 2.12之前,我们便在项目中集成了Flutter,为了支持空安全,首先得将项目迁移到Dart 2.12版本。

可能存在的问题

1)依赖库不支持空安全

只有在所有的依赖都支持空安全的情况下,才可以在健全的空安全下运行项目,所以需要保证所有依赖库都支持空安全,不过现在大部分第三方库都是支持的。

2)代码量大

不需要一次性迁移完成,指定Dart版本号渐进迁移,避免业务修改Merge代码的问题。下文会有空安全迁移的推荐步骤。

3)契约的更新

契约通常文件很多,一般使用脚本批量生成,如果要修改生成的规则、字段是否可空,尽量在空安全迁移之前或者之后统一处理,防止某些字段的空警告消失。尽量避免给List.add()这种集合操作的方法加?可空操作符。

4)Migrate导致的错误

Migrate是官方提供用来迁移空安全的工具,但是在使用的过程中却存在许多坑点。

  • 不合理的强制转换。将可空强转为非空类型。如Future<T>强转成FutureOr<T?>。注意MapMap<String, dynamic>ObjectObject?dynamic{}与<dynamic, dynamic>{}的区别。 

 

  • 无法正确的识别可空类型,可能也与原始代码的实现方式有关。会增加代码判空复杂度。

  • 无理的非空。

  • 一些基础库的泛型没标识非空,无法正常加 ? 标识符。

  • 还会有一些遗留问题,代码上标识为错误和黄底警告,比如多余的?操作符等,都需要手动修改。

5)analysis_options文件中exclude的文件会被Migrate工具忽略,同时也会被空安全语法的代码检测忽略。

6)空安全迁移后还有type 'Null' is not a subtype of type 'xxx' 、Null check operator used on a null value错误。

迁移完空安全后可以免大部分空错误,还会存在一小部分空错误,这是由于!操作符不合理的使用,dymamic 隐式转换等原因导致的,需要避免使用强制非空以及静态代码扫描来检测。

空安全迁移的推荐步骤

1)flutter pub outdated --mode=null-safety 保证所有库都支持,flutter pub upgrade --null-safety 升级所有依赖库到支持版本。

2)dart migrate --skip-import-check打开migrate,反选所有文件,点击apply,会自动的升级pubspec.yaml版本并给所有文件加上@dart=2.9注释。

3)自底向上的适配项目中的文件。将文件的@dart=2.9注释删除会出现很多空安全错误和警告,警告也需要修改。(如果要用Migrate修改一定要对检查每个改动)

迁移顺序:公共库 → 业务基础库、Utils、Model → ViewModel → Widget → main.dart

4)main.dart的@dart=2.9移除后,项目将以健全的空安全模式运行。

2.3 配置静态代码扫描 

静态代码扫描

本文标签: 干货代码质量FlutterTrip