#flutter
#flutter
Вопрос:
Я бы хотел, чтобы FutureBuilder дождался, пока пользователь сделает выбор в маршруте или диалоговом окне (пример ниже), а затем вернул эти данные в конструктор. Однако диалоговое окно никогда не появляется.
Как я могу дождаться возврата данных с экрана или диалогового окна с использованием FutureBuilder?
import 'package:flutter/material.dart';
void main() => runApp(HomeScreen());
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: launch(context),
builder: (context, snapshot) {
// use result from screen or dialog in snapshot.data
return Center(child: Text(snapshot.data));
}),
),
);
}
Future launch(BuildContext context) async {
return await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
actions: <Widget>[
FlatButton(
child: Text('Send Data'),
onPressed: () {
// return some data
Navigator.pop(context, 'Some data!');
},
),
],
content: Container(child: Text('')),
);
},
);
}
}
Ответ №1:
Вы можете скопировать вставить выполнить полный код ниже
Шаг 1: вам нужно использовать addPostFrameCallback
Шаг 2: переход MaterialApp
на верхний уровень
Шаг 3: проверка ConnectionState
фрагмент кода
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_future = launch(context);
});
});
super.initState();
}
Future<String> launch(BuildContext context) async {
var result = await showDialog(
...
print("result $result");
return Future.value(result);
}
рабочая демонстрационная ссылка на dartpad
полный код
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Future<String> _future;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_future = launch(context);
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return Center(child: Text("his this is ${snapshot.data}"));
}
}
}),
),
);
}
Future<String> launch(BuildContext context) async {
var result = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
actions: <Widget>[
FlatButton(
child: Text('Send Data'),
onPressed: () {
// return some data
Navigator.pop(context, 'Some data!');
},
),
],
content: Container(child: Text('')),
);
},
);
print("result $result");
return Future.value(result);
}
}
Ответ №2:
Спасибо за возврат используйте future Completer для получения данных из диалога
создайте более полный экземпляр
var dialogueFuture = Completer();
передайте future of completer в Future builder
FutureBuilder{
future : dialogueFuture.future,
...
}
в функции показать диалог завершите будущее следующим образом
var theData = await showDialogue(...)
dialogFuture.complete(theData);
смотрите панель для рисования здесь
Комментарии:
1.
Navigator.pop()
не возвращает Future, поэтому его нельзяawait
редактировать.2. добавлена ссылка на dartpad
3. ShowDialog возвращает Future<bool?>. Это то, чего он ждет.