从 Dart 中的构造函数调用异步方法

问题描述 投票:0回答:4

我们假设 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
asynchronous constructor dart
4个回答
156
投票

处理此问题的最佳方法可能是使用工厂函数,它调用私有构造函数。

在 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");
}

这样,就不可能意外地从类中创建未正确初始化的对象。唯一可用的构造函数是私有的,因此创建对象的唯一方法是使用工厂,它执行正确的初始化。


113
投票

构造函数只能返回它是其构造函数的类的实例 (

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
立即返回,否则它会等待未来先完成。


2
投票

我同意,异步工厂函数将帮助 Dart 开发人员解决这个问题。 @kankaristo 恕我直言给出了最好的答案,一个静态异步方法,返回一个完全构造和初始化的对象。你必须以某种方式处理异步,将 init 分成两部分会导致错误。


0
投票

我也遇到这个问题了 按照此链接中的步骤操作 https://flutterigniter.com/build-widget-with-async-method-call/

© www.soinside.com 2019 - 2024. All rights reserved.