如何检查 'late' 变量是否已在 Dart 中初始化
How to check 'late' variable is initialized in Dart
在 kotlin 中我们可以检查 'late' 类型变量是否像下面这样初始化
lateinit var file: File
if (this::file.isInitialized) { ... }
是否可以在 Dart 中做类似的事情..?
很遗憾,这是不可能的。
来自文档:
AVOID late variables if you need to check whether they are initialized.
Dart offers no way to tell if a late variable has been initialized or
assigned to. If you access it, it either immediately runs the
initializer (if it has one) or throws an exception. Sometimes you have
some state that’s lazily initialized where late might be a good fit,
but you also need to be able to tell if the initialization has
happened yet.
Although you could detect initialization by storing the state in a
late variable and having a separate boolean field that tracks whether
the variable has been set, that’s redundant because Dart internally
maintains the initialized status of the late variable. Instead, it’s
usually clearer to make the variable non-late and nullable. Then you
can see if the variable has been initialized by checking for null.
Of course, if null is a valid initialized value for the variable, then
it probably does make sense to have a separate boolean field.
如果有人在路上遇到它可能会杀了你,但你可以将它包裹在 try/catch/finally 中进行检测。我喜欢它胜过单独的布尔值。
我们有一个实例,如果小部件无法加载并包含一个在加载时填充的延迟控制器,则会将其丢弃。由于控制器为空,因此处理失败,但这是控制器可以为空的唯一情况。我们将 dispose 包裹在一个 try catch 中来处理这种情况。
您可以创建 Late class 并使用如下扩展:
import 'dart:async';
import 'package:flutter/foundation.dart';
class Late<T> {
ValueNotifier<bool> _initialization = ValueNotifier(false);
late T _val;
Late([T? value]) {
if (value != null) {
this.val = value;
}
}
get isInitialized {
return _initialization.value;
}
T get val => _val;
set val(T val) => this
.._initialization.value = true
.._val = val;
}
extension LateExtension<T> on T {
Late<T> get late => Late<T>();
}
extension ExtLate on Late {
Future<bool> get wait {
Completer<bool> completer = Completer();
this._initialization.addListener(() async {
completer.complete(this._initialization.value);
});
return completer.future;
}
}
用isInitialized创建后期变量属性:
var lateString = "".late;
var lateInt = 0.late;
//or
Late<String> typedLateString = Late();
Late<int> typedLateInt = Late();
并像这样使用:
print(lateString.isInitialized)
print(lateString.val)
lateString.val = "initializing here";
甚至你可以等待初始化 class:
Late<String> lateVariable = Late();
lateTest() async {
if(!lateVariable.isInitialized) {
await lateVariable.wait;
}
//use lateVariable here, after initialization.
}
我从不同的 dart 维护者的建议中得出的一些技巧,以及我的自我分析:
late
使用技巧:
- 如果稍后要检查变量的初始化,请不要对变量使用
late
修饰符。
- 不要对面向public的变量使用
late
修饰符,仅对私有变量(前缀为_
)使用。初始化的责任不应委托给 API 用户。 编辑:与Irhn mentioned一样,这条规则只对没有初始化表达式的late final
变量有意义,它们不应该是public。否则有公开 late
变量的有效用例。请看他的描述性评论!
- 确保在所有构造函数中初始化
late
变量,退出和 新兴 变量。
- 在无法访问的代码场景中初始化
late
变量时要小心。例子:
late
变量在 if
子句中初始化,但在 else
中没有初始化,反之亦然。
- 一些控制流 short-circuit/early-exit 阻止执行到达初始化
late
变量的行。
请指出任何errors/additions。
尽情享受吧!
来源:
- eernstg's take
- Hixie's take
- lrhn's take
- leafpetersen's final verdict as of 2021 10 22
- Effective Dart
- 关于如何用一些常识来处理这个问题的自我分析。
我在初始化后期变量时使用布尔变量。
我的情况是:
我正在使用音频播放器,我需要一个 dart 文件中的流。
我正在分享我的代码块,这种方法可以使用全局布尔变量轻松实现到项目中。
我的问题是当用户快速打开和关闭页面时我从处理方法中得到的异常
在 kotlin 中我们可以检查 'late' 类型变量是否像下面这样初始化
lateinit var file: File
if (this::file.isInitialized) { ... }
是否可以在 Dart 中做类似的事情..?
很遗憾,这是不可能的。
来自文档:
AVOID late variables if you need to check whether they are initialized.
Dart offers no way to tell if a late variable has been initialized or assigned to. If you access it, it either immediately runs the initializer (if it has one) or throws an exception. Sometimes you have some state that’s lazily initialized where late might be a good fit, but you also need to be able to tell if the initialization has happened yet.
Although you could detect initialization by storing the state in a late variable and having a separate boolean field that tracks whether the variable has been set, that’s redundant because Dart internally maintains the initialized status of the late variable. Instead, it’s usually clearer to make the variable non-late and nullable. Then you can see if the variable has been initialized by checking for null.
Of course, if null is a valid initialized value for the variable, then it probably does make sense to have a separate boolean field.
如果有人在路上遇到它可能会杀了你,但你可以将它包裹在 try/catch/finally 中进行检测。我喜欢它胜过单独的布尔值。
我们有一个实例,如果小部件无法加载并包含一个在加载时填充的延迟控制器,则会将其丢弃。由于控制器为空,因此处理失败,但这是控制器可以为空的唯一情况。我们将 dispose 包裹在一个 try catch 中来处理这种情况。
您可以创建 Late class 并使用如下扩展:
import 'dart:async';
import 'package:flutter/foundation.dart';
class Late<T> {
ValueNotifier<bool> _initialization = ValueNotifier(false);
late T _val;
Late([T? value]) {
if (value != null) {
this.val = value;
}
}
get isInitialized {
return _initialization.value;
}
T get val => _val;
set val(T val) => this
.._initialization.value = true
.._val = val;
}
extension LateExtension<T> on T {
Late<T> get late => Late<T>();
}
extension ExtLate on Late {
Future<bool> get wait {
Completer<bool> completer = Completer();
this._initialization.addListener(() async {
completer.complete(this._initialization.value);
});
return completer.future;
}
}
用isInitialized创建后期变量属性:
var lateString = "".late;
var lateInt = 0.late;
//or
Late<String> typedLateString = Late();
Late<int> typedLateInt = Late();
并像这样使用:
print(lateString.isInitialized)
print(lateString.val)
lateString.val = "initializing here";
甚至你可以等待初始化 class:
Late<String> lateVariable = Late();
lateTest() async {
if(!lateVariable.isInitialized) {
await lateVariable.wait;
}
//use lateVariable here, after initialization.
}
我从不同的 dart 维护者的建议中得出的一些技巧,以及我的自我分析:
late
使用技巧:
- 如果稍后要检查变量的初始化,请不要对变量使用
late
修饰符。 - 不要对面向public的变量使用
late
修饰符,仅对私有变量(前缀为_
)使用。初始化的责任不应委托给 API 用户。 编辑:与Irhn mentioned一样,这条规则只对没有初始化表达式的late final
变量有意义,它们不应该是public。否则有公开late
变量的有效用例。请看他的描述性评论! - 确保在所有构造函数中初始化
late
变量,退出和 新兴 变量。 - 在无法访问的代码场景中初始化
late
变量时要小心。例子:late
变量在if
子句中初始化,但在else
中没有初始化,反之亦然。- 一些控制流 short-circuit/early-exit 阻止执行到达初始化
late
变量的行。
请指出任何errors/additions。
尽情享受吧!
来源:
- eernstg's take
- Hixie's take
- lrhn's take
- leafpetersen's final verdict as of 2021 10 22
- Effective Dart
- 关于如何用一些常识来处理这个问题的自我分析。
我在初始化后期变量时使用布尔变量。 我的情况是: 我正在使用音频播放器,我需要一个 dart 文件中的流。
我正在分享我的代码块,这种方法可以使用全局布尔变量轻松实现到项目中。 我的问题是当用户快速打开和关闭页面时我从处理方法中得到的异常