Why null safety?
空安全是一个非常具有生产力的功能,能够帮助你避免空异常。除此之外它也能有一定程度上的性能提升。
Dart是一个类型安全的语言。这意味着当你定义了某类型的变量时,编译器可以保证该变量是确定的类型。当时却无法保证该类型是非空的。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
// This app simulates possible null errors. Try running it and see if it fails.
// You can then try to hot reload a few times; you should see it occasionally
// failing and occasionally succeeding.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get data from services. Note: in a real application,
// these would be async calls, but we’re using sync calls
// for simplicity.
final localizedAppName = Config.getAppName();
final temperatures = WeatherService.getTemperatures();
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text(localizedAppName)),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Temperature next 3 days:'),
for (final t in temperatures) Text(t.round().toString()),
],
),
),
),
);
}
}
class Config {
static String getAppName() {
// Imagine this looks up a localized version of the app name. We're using
// the current time to simulate a variance in responses.
if (DateTime.now().second.isEven) {
return 'Weather forecast';
} else {
// Oops, we don't have a localization.
return null;
}
}
}
class WeatherService {
static List<double> getTemperatures() {
// Imagine this makes a network call to get the current temperature.
// We're using the current time to simulate a variance in responses.
if (DateTime.now().millisecond.isEven) {
return [32.2, 34.5, 31.0];
} else {
if ((DateTime.now().second / 10).round().isEven) {
// Oops, we couldn't get any temperatures.
return null;
} else {
// Oops, we couldn't get one of the temperatures.
return [32.2, 34.5, null, 31.0];
}
}
}
}
以上代码将会在 for loop 和Text文本出现空异常。
Screenshot of the preceding code with null errors而对于空安全检查,编译器将会分析代码,对于为空的位置以红色波浪形做出提示。
Null safety principles
1.Non-nullable by default.除非显示指定某个变量可为空,否则都会被编译器视为非空。
// In null-safe Dart, none of these can ever be null.
var widget = Text('Hello');
final status = GetStatus();
String m = '';
对于以上代码,如果在项目中之后的代码将widget设置为null,开发者将会得到静态分析错误和红色波浪线提示,编译器也会拒绝编译。
1.1 Nullable variables
如果你想要设置某个变量可以为空,可以使用?,比如
// These are all nullable variables.
Text? t = Text('Hello'); // Can be null later.
final Status? s = getStatus(); // Maybe the function returns null.
String? n; // Is null at first. Can be null at any later time, too.
也可以设置函数参数和返回值为空
// In function parameters.
void initialize(int? count) {
// It's possible that count is null.
}
// In function return values.
static List<double?>? getTemperatures() {
// Can return null instead of a List, and the list can contain nulls.
}
1.2 Being productive with null safety
空安全并不仅仅是关于安全,也是简单易用,具备生产力的。
void honk(int? loudness) {
if (loudness == null) {
// No loudness specified, notify the developer
// with maximum loudness.
_playSound('error.wav', volume: 11);
return;
}
// Loudness is non-null, let's just clamp it to acceptable levels.
_playSound('honk.wav', volume: loudness.clamp(0, 11));
}
2.Incrementally adoptable.开发者可以自主选择迁移时间,并且一部分一部分迁移。在同一个工程内可以同时有空安全代码和非空安全代码。同时为开发者提供了帮助迁移的工具。基于稳定性考虑,在进行项目迁移的时候官方建议根据依赖顺序进行。
3.Fully sound. Dart空安全是非常健全的。这意味着我们完全可以信任类型系统:如果它判定某个对象非空,那就肯定不会为null。只要把工程和依赖迁移到空安全,不仅会减少代码,也会生成更小的二进制文件和更快的执行效率。
The null safety roadmap
1.Flutter experimentation with *technical preview 2*:当前阶段;
2.Early package migration with *beta*: 今年晚些时候;
3.Production use with stable:大概在明年;
网友评论