web-dev-qa-db-ja.com

Futter FutureBuilderテキストフィールド値が変更されたときに更新されます

__futureData_は、_loadPhobias()関数から値を取得した後のFutureBuilderに使用されます。

entry_screen.dart

_Future _futureData;
final TextEditingController _textEditingController = TextEditingController();
_

_loadPhobias()関数は問題がないようです。

entry_screen.dart

_Future<List<String>> _loadPhobias() async =>
    await rootBundle.loadString('assets/phobias.txt').then((phobias) {
    List _listOfAllPhobias = [];
    List<String> _listOfSortedPhobias = [];
    _textEditingController.addListener(() {
      ...
    }); 
    return _listOfSortedPhobias;
});

@override
void initState() {
super.initState();
    _futureData = _loadPhobias();
}

@override
Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    title: TextField(
        // When the value is changed, the value returned from the _loadPhobias will also change. So I want the FutureBuilder to be rebuilt.
        onChanged: (text) { setState(() => _futureData =  _loadPhobias()) },
        ),
    ),
    body: FutureBuilder(
        future: _futureData,
        builder: (context, snapshot) {
            return snapshot.hasData
                ? ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, index) => Column(
                            children: <Widget>[
                                PhobiasCard(sentence: snapshot.data[index]),
                            )
                        ],
                    ))
                    : Center(
                        child: CircularProgressIndicator(),
                    );
                },
            ),
        ),
    );
}
_

これが私が得たエラーです。

FlutterErrror(setState()コールバック引数は未来を返しました。

_entryScreenState#51168のsetState()メソッドは、将来を返したクロージャまたはメソッドで呼び出されました。多分それは「非同期」とマークされています。

SetState()への呼び出し内の非同期作業を実行する代わりに、まず作業を実行して(ウィジェット状態を更新せずに)、次にSetState()への呼び出し内の状態を同期的に更新します。)

2
Der Programmer

ソリューションは、エラーメッセージの3行目で推測できます。

SetState()への呼び出し内の非同期作業を実行する代わりに、まず作業を実行して(ウィジェット状態を更新せずに)、次にSetState()への呼び出し内の状態を同期的に更新します。)

したがって、これはウィジェットを更新する前に操作を実行する必要があることを意味します。非同期作業の結果を保持し、それをsetStateメソッドに使用するための一時変数を持つことができます。

onChanged: (text) {
     setState(() => _futureData =  _loadPhobias())
},
 _

次のように書くことができます。

onChanged: (text) async {
    var phobias = _loadPhobias();
    setState(() {
        _futureData = phobias;
    });
},
 _
0