コンシューマウィジェット(プロバイダーパッケージ)内のナビゲーターで置換をプッシュしようとすると、「ビルド中にsetState()またはmarkNeedsBuild()が呼び出されました」エラーが発生しました

ダビデビセゴ

今週、私はフラッターで開発を始めました、そして私はこの問題を解決することができません。

APIを呼び出してログインし、ホームページにリダイレクトした後のログインページを作成しています。これは、Navigator.pushReplacement最初のコードブロックで生成さた例外です。その瞬間apiCall.isFetching、フェッチが終了しapiCall.response、必要なデータが含まれているのは誤りです。

例外の詳細:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building Consumer<ApiCallChangeNotifier>(dirty, dependencies: [InheritedProvider<ApiCallChangeNotifier>]):
setState() or markNeedsBuild() called during build.

This 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.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#4dc85]
  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)])
The widget which was currently being built when the offending call was made was: Consumer<ApiCallChangeNotifier>
  dirty
  dependencies: [InheritedProvider<ApiCallChangeNotifier>]
User-created ancestor of the error-causing widget was: 
  Expanded file:///C:/flutter_test/lib/screens/login/LoginScreen.dart:153:37
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3687:11)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3702:6)
#2      State.setState (package:flutter/src/widgets/framework.dart:1161:14)
#3      OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:346:5)
#4      OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24)
...

これがログインボタンを作成する私の関数です。これLoginScreen(StatelessWidget)のビルド関数から呼び出されます。

Widget loginButton(BuildContext context) {
    return Consumer<ApiCallChangeNotifier>(
        builder: (context, apiCall, child) => apiCall.isFetching
            ? CircularProgressIndicator()
            : apiCall.response != null
                ? Navigator.pushReplacement(
                    context,
                    MaterialPageRoute(
                        builder: (context) => HomeScreen(
                            (apiCall.response as LoginResponse).email)))
                : RaisedButton( 
                     ...
                     onPressed: () {
                         attemptLogin(context);
                     },
                     ...
                  ));
  }

tryLogin機能:

void attemptLogin(BuildContext context) {
    Provider.of<ApiCallChangeNotifier>(context, listen: false).callApi(
        MyApiServices().attemptLogin,
        {
          'email': emailController.value.text,
          'password': passwordController.value.text,
        },
        urlController.value.text
    );
  }

ApiCallChangeNotifier

class ApiCallChangeNotifier extends ChangeNotifier {
  bool isFetching = false;
  Object response;

  Future<LoginResponse> callApi(apiFunction, bodyParams, customUrl) async {
    isFetching = true;
    notifyListeners();

    response = await apiFunction(bodyParams, customUrl);

    isFetching = false;
    notifyListeners();
    return response;
  }
}

MyApiServices.attemptLogin API呼び出しを処理し、オブジェクトLoginResponseを返す関数です。

私が十分な情報を与えたことを願っています!

ダビデビセゴ

から新しいルートをプッシュしようとする代わりに、LoginResponse ConsumerattemptLogin()を変更して、結果を待ち、新しいルートに移動しました。

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)));
      }
    }
  }

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ