簡體   English   中英

Flutter MaterialApp中,在LocaleResolutionCallback內部使用Provider出錯

[英]In Flutter MaterialApp, using Provider inside LocaleResolutionCallback has an error

在我的 flutter 項目中,我為 DI 選擇riverpod_hook

為了根據移動設備的語言設置更改應用程序的語言設置,我編寫了如下代碼。

// app.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class Application extends ConsumerWidget {
  const Application({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return MaterialApp(
      theme: defaultTheme,
      localizationsDelegates: Resource.localizationsDelegates,
      supportedLocales: Resource.supportedLocales,
      localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
        if (supportedLocales.any((element) => locale?.languageCode.contains(element.toString()) == true)) {
          ref.watch(localeCodeProvider.notifier).state = locale!.languageCode;
          return locale;
        }
        return const Locale('ko', '');
      },
      routes: {
        homePageRoutes: (_) => const HomePage(),
        detailPageRoutes: (_) => const DetailPage(),
      },
    );
  }
}

import 'package:hooks_riverpod/hooks_riverpod.dart';

final localeCodeProvider = StateProvider<String>((ref) => 'en');

當我運行這段代碼時,發生了這個錯誤。

E/flutter ( 3747): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Tried to modify a provider while the widget tree was building.
E/flutter ( 3747): If you are encountering this error, chances are you tried to modify a provider
E/flutter ( 3747): in a widget life-cycle, such as but not limited to:
E/flutter ( 3747): - build
E/flutter ( 3747): - initState
E/flutter ( 3747): - dispose
E/flutter ( 3747): - didUpdateWidget
E/flutter ( 3747): - didChangeDepedencies
E/flutter ( 3747): 
E/flutter ( 3747): Modifying a provider inside those life-cycles is not allowed, as it could
E/flutter ( 3747): lead to an inconsistent UI state. For example, two widgets could listen to the
E/flutter ( 3747): same provider, but incorrectly receive different states.
E/flutter ( 3747): 
E/flutter ( 3747): 
E/flutter ( 3747): To fix this problem, you have one of two solutions:
E/flutter ( 3747): - (preferred) Move the logic for modifying your provider outside of a widget
E/flutter ( 3747):   life-cycle. For example, maybe you could update your provider inside a button's
E/flutter ( 3747):   onPressed instead.
E/flutter ( 3747): 
E/flutter ( 3747): - Delay your modification, such as by encasuplating the modification
E/flutter ( 3747):   in a `Future(() {...})`.
E/flutter ( 3747):   This will perform your upddate after the widget tree is done building.

從報錯信息可以看出,錯誤的發生是因為build function內部使用了provider watch

但是,我不願意使用localeResolutionCallback屬性,因為我想設置移動設備的語言設置值並設置整個應用程序的語言。

在這種情況下,我能否獲得有關如何使用provider的適當解決方案?

嘗試調用 WidgetsBinding.instance.addPostFrameCallback 是否可行,如下所示:

if (supportedLocales.any((element) => locale?.languageCode.contains(element.toString()) == true)) {

        WidgetsBinding.instance.addPostFrameCallback((_) {          
                 ref.watch(localeCodeProvider.notifier).state = 
                          locale!.languageCode;
         });

  return locale;
}

它的作用 - 它允許您完成構建; 然后更改提供者 - 這很可能會調用另一個構建。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM