やりたかったこと
setState
しても二度目の非同期処理が走らない状態にしたかった。
起こった問題
以前書いたFutureBuilder で future に入れた値はどこに行くのか分からなくて四苦八苦した話。でやったように、
future
に直接、非同期処理の関数を入れていたら、setState
するたびに非同期処理が走ってしまった。
例えば、チェックボックス Widget で onChanged
するときに setState
でチェックを入れたかのフラグを切り替えたりするけど、
チェックボックスにチェックを入れるたびに、くるくる画面になってしまうイメージ。これは良くない。
解決策
initState
に非同期処理の結果値を入れたら解決した。
どういうことかというと以下のコードがわかりやすいだろう。
class _SampleState extends State<Sample> { bool isChecked = false; late Future<String> _version; // Future型のフィールドとしてクラスに定義しておく @override void initState() { _version = _getVersion(); // 非同期処理をフィールドに入れる super.initState(); } Future<String> _getVersion() async { return await sampleService.getVersion(); // 非同期処理 } @override Widget build(BuildContext context) { return FutureBuilder( future: _version, // initで入れたフィールド builder: (BuildContext context, AsyncSnapshot<String> snapshot) { Widget childWidget; if (snapshot.connectionState == ConnectionState.done) { // 非同期処理完了時 if (snapshot.hasError) { // 非同期処理でエラーが起きた時 childWidget = _errorDisplay(); } childWidget = Text('${snapshot.data}'); // 非同期処理で得られた結果。 } else { childWidget = const CircularProgressIndicator(); } return childWidget; }, ); } }