空安全
大约 3 分钟projs
空安全的原则
Dart 的空安全支持基于以下三条核心原则:
默认不可空:除非您将变量显式声明为可空,否则它一定是非空的类型;
渐进迁移:您可以自由地选择何时进行迁移,多少代码会进行迁移;
完全可靠:Dart 的空安全是非常可靠的,意味着编译期间包含了很多优化,如果类型系统推断出某个变量不为空,那么它 永远 不为空。当您将整个项目和其依赖完全迁移至空安全后,您会享有健全性带来的所有优势——更少的 BUG、更小的二进制文件以及更快的执行速度。
可空类型 ?
我们可以通过将?跟在类型的后面来表示它后面的变量或参数可接受Null
class CommonModel {
String? firstName; //可空的成员变量
int getNameLen(String? lastName /*可空的参数*/) {
int firstLen = firstName?.length ?? 0;
int lastLen = lastName?.length ?? 0;
return firstLen + lastLen;
}
}
对于可空的变量或参数在使用的时候需要通过Dart 的避空运算符?.来进行访问,否则会抛出编译错误。当程序启用空安全后,类的成员变量默认是不可空的,所以对于一个非空的成员变量需要指定其初始化方式
lass CommonModel {
List names=[];//定义时初始化
final List colors;//在构造方法中初始化
late List urls;//延时初始化
CommonModel(this.colors);
延迟初始化 late
对于无法在定义时进行初始化,并且又想避免使用?.,那么延迟初始化可以帮到你。通过late修饰的变量,可以让开发者选择初始化的时机,并且在使用这个变量时可以不用?.。
late List urls;//延时初始化
setUrls(List urls){
this.urls=urls;
}
int getUrlLen(){
return urls.length;
}
延迟初始化虽然能为我们编码带来一定便利,但如果使用不当会带来空异常的问题,所以在使用的时候一定保证赋值和访问的的顺序,切莫颠倒。延迟初始化(late)使用范式在 Flutter 中 State 的 initState 方法中初始化的一些变量是比较适合使用 late 来进行延时初始化的,因为在 Widget 生命周期中initState 方法是最先执行的,所以它里面初始化的变量通过 late 修饰后既能保障使用时的便利,又能防止空异常,看下具体的用法.
class _TravelPgeState extends State<TravelPge> with TickerProviderStateMixin {
List<TravelTab> tabs = [];
TravelCategoryModel? travelTabModel;
late TabController _controller;
void initState() {
super.initState();
_controller = TabController(length: 0, vsync: this);
}
}
空值断言 !
当我们排除变量或参数的可空的可能后,可以通过!来告诉编译器这个可空的变量或参数不可空,这对我们进行方法传参或将可空参数传递给一个不可空的入参时特别有用
get _listView => ListView(
children: [
BannerWidget(bannerList: bannerList),
LocalNavWidget(localNavList: localNavList),
if (gridNavModel != null) GridNavWidget(gridNavModel: gridNavModel!),
SubNavWidget(suNavList: subNavList),
if (salesBoxModel != null) SalesBoxWidget(salesBox: salesBoxModel!),
_logoutBtn,
const SizedBox(
height: 800,
child: ListTile(
title: Text('哈哈'),
),
)
],
);
除此之外,!还有一个常见的用处就是取反
bool isEmptyList(Object object) {
if (object is! List) return false;
return object.isEmpty;
}
// 用在这里表示取反,上述代码等价于:
bool isEmptyList(Object object) {
if (!(object is List)) return false;
return object.isEmpty;
}
