Flutter go_router, как вернуть результат на предыдущую страницу?
Я пытаюсь открыть страницу и получить возвращаемый результат с пакетом go_router. В Navigation 1.0 я использую это:
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
// handle result
Но я не могу сделать это с помощью go_router. Любое решение или объяснение?
10 ответов
Последняя версия пакета go_router теперь поддерживает эту функцию. Чтобы передать данные при выходе из экрана, вы можете сделать это:
context.pop('value');
И чтобы вернуть это значение, ваш код должен выглядеть так:
String? val = await context.pushNamed('secondRoute');
Надеюсь, это поможет, спасибо
Вы можете сделать это сGoRouter.of(context).addListener
.
Сначала вы отправляете свою новую страницу, а затем добавляете слушателя
GoRouter.of(context).push("/page/${page!.id}/edit");
GoRouter.of(context).addListener(watchRouteChange);
Функция слушателя может выглядеть примерно так
watchRouteChange() {
if (!GoRouter.of(context).location.contains("/edit")) { // Here you check for some changes in your route that indicate you are no longer on the page you have pushed before
// do something
GoRouter.of(context).removeListener(watchRouteChange); // remove listener
}
}
В настоящее время нет способа добиться этого с помощью . Вы можете использоватьgo_router_flow
что точно похожеgo_router
с этой поп-функцией значения.
final bool? result = await context.push<bool>('/page2');
WidgetsBinding.instance.addPostFrameCallback((_) {
if(result){
print('Page returned $result');
}
});
Вы можете использовать обратный вызов, поместив функцию в дополнительный объект при нажатии нового экрана.
Пример экрана A -push-> Screen B ->pop with result -> Screen A (получить результаты)
- Определите тип функции, чтобы поместить
typedef AddNewEventResult = void Function(Result result);
- Нажмите А -> Б
GoRoute(
path: kScreenB,
builder: (BuildContext context, GoRouterState state) => ScreenB(addNewEventResultstate.extra! as AddNewEventResult),
)
- Когда экран B будет готов, просто перетащите его из B в A и прикрепите результат (Результат).
Navigator.of(context).pop();
widget.addNewEventResult(true, Result());
Этот поток описан в документации здесь: https://gorouter.dev/user-input
Как правило, вам нужно обновить данные и вернуть некоторое значение обратно в виде маршрута с параметрами, а сам экран должен управлять обновлениями/манипулированием данными.
Я не хочу копировать их код здесь, но ответ, который вы ищете, находится на странице документации выше.
К сожалению, в настоящее время GoRouter не предоставляет искомую функциональность .
Альтернативой использованию go_router_flow является самостоятельная реализация чего-то простого путем передачи обратных вызовов в качестве дополнительного свойства в GoRouterState.
Этот дротик содержит полный пример, но суть в том, что вы определяете свои маршруты примерно так:
GoRouter(
initialLocation: "/",
routes: <RouteBase>[
GoRoute(
path: "/second",
builder: (_, state) {
final params = state.extra! as SecondPageParams;
return SecondPage(params: params);
},
),
],
);
И определите свой аналог:
class SecondPageParams {
final void Function(String data) action;
const SecondPageParams(this.action);
}
class SecondPage extends StatelessWidget {
final SecondPageParams params;
const SecondPage({super.key, required this.params});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
context.pop();
params.action("Data from second page");
},
child: const Text("Pop and perform action")
),
),
),
);
}
}
Это не так чисто, как возможностьawait
аcontext.push
, но это простой способ указать действие, которое вы хотитеSecondPage
извлекается из стека без необходимости полагаться на другой пакет.
в документации: https://pub.dev/documentation/go_router/latest/topics/Navigation-topic.html .
Ожидание возврата значения:
onTap: () {
final bool? result = await context.push<bool>('/page2');
if(result ?? false)...
}
Возврат значения:
onTap: () => context.pop(true)
На момент ответа только поддержка выполнения
List<Archive> selectArchives = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const ArchiveListPage(
selectMode: true, canSelectCount: 1)));
context.pop(_selectArchives);
если вы используете Gorouter, вы можете использовать
GoRouter.of(контекст).pop();
Когда вы закончите со следующим экраном, просто используйте
Navigator.pop(context,true);
а также
true
это то, что вы хотите отправить на предыдущий экран. Вы можете отправить все, что я использую как true для справки. Это позволит вашему
result
переменная для получения данных и выполнения чего-либо.