我们假设 Dart 中 MyComponent 的初始化需要向服务器发送 HttpRequest。是否可以同步构造一个对象并推迟“真正的”初始化直到响应返回?
在下面的示例中,直到打印“done”后才会调用 _init() 函数。这个问题可以解决吗?
import 'dart:async';
import 'dart:io';
class MyComponent{
MyComponent() {
_init();
}
Future _init() async {
print("init");
}
}
void main() {
var c = new MyComponent();
sleep(const Duration(seconds: 1));
print("done");
}
输出:
done
init
处理此问题的最佳方法可能是使用工厂函数,它调用私有构造函数。
在 Dart 中,私有方法以下划线开头,并且“附加”构造函数需要采用
ClassName.constructorName
形式的名称,因为 Dart 不支持函数重载。这意味着私有构造函数需要一个以下划线开头的名称(在下面的示例中为MyComponent._create
)。
import 'dart:async';
import 'dart:io';
class MyComponent{
/// Private constructor
MyComponent._create() {
print("_create() (private constructor)");
// Do most of your initialization here, that's what a constructor is for
//...
}
/// Public factory
static Future<MyComponent> create() async {
print("create() (public factory)");
// Call the private constructor
var component = MyComponent._create();
// Do initialization that requires async
//await component._complexAsyncInit();
// Return the fully initialized object
return component;
}
}
void main() async {
var c = await MyComponent.create();
print("done");
}
这样,就不可能意外地从类中创建未正确初始化的对象。唯一可用的构造函数是私有的,因此创建对象的唯一方法是使用工厂,它执行正确的初始化。
构造函数只能返回它是其构造函数的类的实例 (
MyComponent
)。您的要求需要构造函数返回 Future<MyComponent>
,但不受支持。
您要么需要创建一个需要由类的用户调用的显式初始化方法,例如:
class MyComponent{
MyComponent();
Future init() async {
print("init");
}
}
void main() async {
var c = new MyComponent();
await c.init();
print("done");
}
或者您在构造函数中开始初始化并允许组件的用户等待初始化完成。
class MyComponent{
Future _doneFuture;
MyComponent() {
_doneFuture = _init();
}
Future _init() async {
print("init");
}
Future get initializationDone => _doneFuture
}
void main() async {
var c = new MyComponent();
await c.initializationDone;
print("done");
}
当
_doneFuture
已经完成时 await c.initializationDone
立即返回,否则它会等待未来先完成。
我同意,异步工厂函数将帮助 Dart 开发人员解决这个问题。 @kankaristo 恕我直言给出了最好的答案,一个静态异步方法,返回一个完全构造和初始化的对象。你必须以某种方式处理异步,将 init 分成两部分会导致错误。
我也遇到这个问题了 按照此链接中的步骤操作 https://flutterigniter.com/build-widget-with-async-method-call/