Dav*_*ego 8 dart flutter flutter-provider
本周我开始在 flutter 中进行开发,但我无法解决这个问题。
\n\n我正在构建一个登录页面,该页面调用 API 进行登录,然后重定向到主页。\n这是第一个代码块中生成的异常。Navigator.pushReplacement\n此时apiCall.isFetching为 false,导致获取结束并apiCall.response包含所需的数据。
异常详细信息:
\n\n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 Exception caught by widgets library \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nThe following assertion was thrown building Consumer<ApiCallChangeNotifier>(dirty, dependencies: [InheritedProvider<ApiCallChangeNotifier>]):\nsetState() or markNeedsBuild() called during build.\n\nThis Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.\nThe widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#4dc85]\n state: OverlayState#bd97e(tickers: tracking 1 ticker, entries: [OverlayEntry#2941b(opaque: false; maintainState: false), OverlayEntry#37814(opaque: false; maintainState: true), OverlayEntry#f92c0(opaque: false; maintainState: false), OverlayEntry#da26d(opaque: false; maintainState: true)])\nThe widget which was currently being built when the offending call was made was: Consumer<ApiCallChangeNotifier>\n dirty\n dependencies: [InheritedProvider<ApiCallChangeNotifier>]\nUser-created ancestor of the error-causing widget was: \n Expanded file:///C:/flutter_test/lib/screens/login/LoginScreen.dart:153:37\nWhen the exception was thrown, this was the stack: \n#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3687:11)\n#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3702:6)\n#2 State.setState (package:flutter/src/widgets/framework.dart:1161:14)\n#3 OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:346:5)\n#4 OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24)\n...\nRun Code Online (Sandbox Code Playgroud)\n\n这是我创建登录按钮的函数,它是从LoginScreen (StatelessWidget)的构建函数调用的
\n\n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 Exception caught by widgets library \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nThe following assertion was thrown building Consumer<ApiCallChangeNotifier>(dirty, dependencies: [InheritedProvider<ApiCallChangeNotifier>]):\nsetState() or markNeedsBuild() called during build.\n\nThis Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.\nThe widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#4dc85]\n state: OverlayState#bd97e(tickers: tracking 1 ticker, entries: [OverlayEntry#2941b(opaque: false; maintainState: false), OverlayEntry#37814(opaque: false; maintainState: true), OverlayEntry#f92c0(opaque: false; maintainState: false), OverlayEntry#da26d(opaque: false; maintainState: true)])\nThe widget which was currently being built when the offending call was made was: Consumer<ApiCallChangeNotifier>\n dirty\n dependencies: [InheritedProvider<ApiCallChangeNotifier>]\nUser-created ancestor of the error-causing widget was: \n Expanded file:///C:/flutter_test/lib/screens/login/LoginScreen.dart:153:37\nWhen the exception was thrown, this was the stack: \n#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3687:11)\n#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3702:6)\n#2 State.setState (package:flutter/src/widgets/framework.dart:1161:14)\n#3 OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:346:5)\n#4 OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24)\n...\nRun Code Online (Sandbox Code Playgroud)\n\nattemptsLogin 函数:
\n\nWidget loginButton(BuildContext context) {\n return Consumer<ApiCallChangeNotifier>(\n builder: (context, apiCall, child) => apiCall.isFetching\n ? CircularProgressIndicator()\n : apiCall.response != null\n ? Navigator.pushReplacement(\n context,\n MaterialPageRoute(\n builder: (context) => HomeScreen(\n (apiCall.response as LoginResponse).email)))\n : RaisedButton( \n ...\n onPressed: () {\n attemptLogin(context);\n },\n ...\n ));\n }\nRun Code Online (Sandbox Code Playgroud)\n\nApiCallChangeNotifier
\n\nvoid attemptLogin(BuildContext context) {\n Provider.of<ApiCallChangeNotifier>(context, listen: false).callApi(\n MyApiServices().attemptLogin,\n {\n \'email\': emailController.value.text,\n \'password\': passwordController.value.text,\n },\n urlController.value.text\n );\n }\nRun Code Online (Sandbox Code Playgroud)\n\nMyApiServices.attemptLogin是一个处理 API 调用并返回 LoginResponse 对象的函数
希望我提供了足够的信息!
\n对我来说,这是我在构建完成之前使用导航器的时候!只需将您的导航代码放在这里即可:
WidgetsBinding.instance.addPostFrameCallback((_) {
// Do everything you want here...
});
Run Code Online (Sandbox Code Playgroud)
LoginResponse Consumer我修改了 attemptsLogin()来等待结果并导航到新路线,而不是尝试推送新路线!
void attemptLogin(BuildContext context) async {
LoginResponse _apiResponse =
await Provider.of<ApiCallChangeNotifier>(context, listen: false)
.callApi(
MyApiServices().attemptLogin,
{
'email': emailController.value.text,
'password': passwordController.value.text,
},
urlController.value.text);
if (_apiResponse != null) {
if (_apiResponse.email != null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(_apiResponse.email)));
} else if (_apiResponse.errorMessage != null) {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text(_apiResponse.errorMessage)));
} else {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(KanbanBOXApi().unknownErrorMessage)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10701 次 |
| 最近记录: |