web-dev-qa-db-ja.com

Dartのコンポーネントコンストラクターから非同期メソッドを呼び出す

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
30
typedef

コンストラクターは、それが(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はすぐに戻ります。それ以外の場合は、将来が最初に完了するのを待ちます。

19

_init()をstaticメソッドとして使用できます。これはあなたの問題のより良い解決策になるかもしれません:

import 'Dart:async';
import 'Dart:io';

class MyComponent{
  MyComponent();
  static Future init() async {
    print("init");
  }
}

void main() async {
  var c = await MyComponent.init();
  sleep(const Duration(seconds: 1));
  print("done");
}

Init()を使用している関数を非同期としてマークすることを忘れないでください。

0
Syed Mushaheed