本节指标

  • 空平安意味着什么
  • 如何迁徙代码
  • 如何禁用空平安
  • 代码标准示例

视频

https://www.bilibili.com/vide...

代码

https://github.com/ducafecat/...

参考

  • https://dart.cn/null-safety
  • https://dart.cn/null-safety/m...
  • https://dart.cn/null-safety/u...
  • https://dart.cn/null-safety/u...
  • https://dart.cn/null-safety/faq

注释

空平安意味着什么

  • 默认不可空
String title = 'ducafecat';
  • type? 操作符
String? title = null;
  • value! 操作符
String? title = 'ducafecat';String newTitle = title!;
  • value? 操作符
String? title = 'ducafecat';bool isEmpty = title?.isEmpty();
  • value?? 操作符
String? title = 'ducafecat';String newTitle = title ?? 'cat';
  • late 会在运行时查看。所以请您仅在确定它被应用前肯定会被初始化的状况下应用
late String? title;title = 'ducafecat';
  • List、泛型
类型汇合是否可空数据项是否可空
List<String>nono
List<String>?yesno
List<String?>noyes
List<String?>?yesyes
  • Map
类型汇合是否可空数据项是否可空
Map<String, int>nono*
Map<String, int>?yesno*
Map<String, int?>noyes
Map<String, int?>?yesyes
* 可能返回空
// 有可能返回 nullint value = <String, int>{'one': 1}['one']; // ERROR// 须要加上 type?int? value = <String, int>{'one': 1}['one']; // OK// 或者 value!int value = <String, int>{'one': 1}['one']!; // OK

带来的益处

  • 代码更衰弱
  • 用户体验好
  • 运行更快
  • 编译文件更小

开启和迁徙

  • pubspec.yaml
environment:  sdk: ">=2.12.0 <3.0.0"
  • 迁徙程序

咱们强烈建议您按程序迁徙代码,先迁徙依赖关系中的处于最末端的依赖。例如,如果 C 依赖了 B,B 依赖了 A,那么应该依照 A -> B -> C 的程序进行迁徙。

  • 查看依赖我的项目
# Dart 版本是否为 2.12 或更高> dart --version# 依赖包的迁徙状态> dart pub outdated --mode=null-safety
  • 降级依赖
# 该命令会更改您的 pubspec.yaml 文件> dart pub upgrade --null-safety# 升级包> dart pub upgrade
  • 迁徙工具
> dart migrate
  • 剖析
> dart analyze

禁用空平安

  • cli 命令
> dart --no-sound-null-safety run> flutter run --no-sound-null-safety
  • .vscode/launch.json
{  // 应用 IntelliSense 理解相干属性。  // 悬停以查看现有属性的形容。  // 欲了解更多信息,请拜访: https://go.microsoft.com/fwlink/?linkid=830387  "version": "0.2.0",  "configurations": [    {      "name": "getx_quick_start",      "request": "launch",      "type": "dart",      "program": "lib/main.dart",      "args": ["--no-sound-null-safety"]    }  ]}

范例、标准

https://dart.cn/null-safety/u...

  • 明确解决空状态
makeCoffee(String coffee, [String? dairy]) {  if (dairy != null) {    print('$coffee with $dairy');  } else {    print('Black $coffee');  }}
  • 顶层变量和动态字段必须蕴含一个初始化办法。因为它们能在程序里的任何地位被拜访到,编译器无奈保障它们在被应用前已被赋值。惟一保险的选项是要求其自身蕴含初始化表达式,以确保产生匹配的类型的值。
int topLevel = 0;class SomeClass {  static int staticField = 0;}
  • 实例的字段也必须在申明时蕴含初始化办法,能够为常见初始化模式,也能够在实例的构造方法中进行初始化。
class SomeClass {  int atDeclaration = 0;  int initializingFormal;  int initializationList;  SomeClass(this.initializingFormal)      : initializationList = 0;}
  • 局部变量的灵便度最高。一个非空的变量 不肯定须要 一个初始化办法。
int tracingFibonacci(int n) {  int result;  if (n < 2) {    result = n;  } else {    result = tracingFibonacci(n - 2) + tracingFibonacci(n - 1);  }  print(result);  return result;}
  • 流程剖析,在这里 Dart 将 object 的类型从它申明的 Object 晋升到了 List。在空平安引入以前,上面的程序无奈运行。
// With (or without) null safety:bool isEmptyList(Object object) {  if (object is List) {    return object.isEmpty; // <-- OK!  } else {    return false;  }}->// Without null safety:bool isEmptyList(Object object) {  if (object is! List) return false;  return object.isEmpty;}
  • 相对的赋值剖析
int tracingFibonacci(int n) {  final int result;  if (n < 2) {    result = n;  } else {    result = tracingFibonacci(n - 2) + tracingFibonacci(n - 1);  }  print(result);  return result;}
  • 无用代码的正告
String checkList(List list) {  if (list?.isEmpty) {    return 'Got nothing';  }  return 'Got something';}
  • 懒加载的变量, late 修饰符是“在运行时而非编译时对变量进行束缚”。这就让 late 这个词语约等于 何时 执行对变量的强制束缚。
// Using null safety:class Coffee {  String? _temperature;  void heat() { _temperature = 'hot'; }  void chill() { _temperature = 'iced'; }  String serve() => _temperature! + ' coffee';}->// Using null safety:class Coffee {  late String _temperature;  void heat() { _temperature = 'hot'; }  void chill() { _temperature = 'iced'; }  String serve() => _temperature + ' coffee';}
  • latefinal 联合应用,与一般的 final 字段不同,您不须要在申明或结构时就将其初始化。您能够稍后在运行中的某个中央加载它。然而您只能对其进行 一次 赋值,并且它在运行时会进行校验。
// Using null safety:class Coffee {  late final String _temperature;  void heat() { _temperature = 'hot'; }  void chill() { _temperature = 'iced'; }  String serve() => _temperature + ' coffee';}
  • 毕传参数,这里的所有参数都必须通过命名来传递。参数 ac 是可选的,能够省略。参数 bd 是必须的,调用时必须传递。在这里请留神,是否必须和是否可空无关。
// Using null safety:function({int? a, required int? b, int? c, required int? d}) {}
  • 形象字段
abstract class Cup {  Beverage get contents;  set contents(Beverage);}->abstract class Cup {  abstract Beverage contents;}
  • 一些赋值计算能够挪动到动态的初始化中。
// Initalized without valuesListQueue _context;Float32List _buffer;dynamic _readObject;Vec2D(Map<String, dynamic> object) {  _buffer = Float32List.fromList([0.0, 0.0]);  _readObject = object['container'];  _context = ListQueue<dynamic>();}->// Initalized with valuesfinal ListQueue _context = ListQueue<dynamic>();final Float32List _buffer = Float32List.fromList([0.0, 0.0]);final dynamic _readObject;Vec2D(Map<String, dynamic> object) : _readObject = object['container'];
  • 可能返回 null 的工厂办法
factory StreamReader(dynamic data) {  StreamReader reader;  if (data is ByteData) {    reader = BlockReader(data);  } else if (data is Map) {    reader = JSONBlockReader(data);  }  return reader;}->factory StreamReader(dynamic data) {  if (data is ByteData) {    // Move the readIndex forward for the binary reader.    return BlockReader(data);  } else if (data is Map) {    return JSONBlockReader(data);  } else {    throw ArgumentError('Unexpected type for data');  }}

© 猫哥

本视频文档

https://ducafecat.tech/2021/0...

GetX Quick Start 代码

https://github.com/ducafecat/...

新闻客户端代码

https://github.com/ducafecat/...

strapi 手册译文

https://getstrapi.cn

微信探讨群 ducafecat

往期视频

  • Dart 编程语言根底
    https://space.bilibili.com/40...
  • Flutter 零根底入门
    https://space.bilibili.com/40...
  • Flutter 实战从零开始 新闻客户端
    https://space.bilibili.com/40...
  • Flutter 组件开发
    https://space.bilibili.com/40...
  • Flutter 组件开发
    https://space.bilibili.com/40...
  • Flutter Bloc
    https://space.bilibili.com/40...
  • Flutter Getx4
    https://space.bilibili.com/40...
  • Docker Yapi
    https://space.bilibili.com/40...