Flutter 错误 - 由于缺少 MaterialApp 祖先而未显示对话框

问题描述 投票:0回答:1

我遇到了与 Flutter 应用程序中缺少 MaterialApp 祖先相关的错误。我的应用程序的结构包括 MultiProvider 和 ModularApp 设置,但我仍然收到有关缺少 MaterialApp 的错误。

这是我的代码结构的简化版本:

// main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(
    ModularApp(
      module: AppModule(),
      child: const AppWidget(),
    ),
  );
}

// AppModule.dart
class AppModule extends Module {
  // ... (module configuration)
}

// AppWidget.dart
class AppWidget extends StatelessWidget {
  const AppWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    LocalJsonLocalization.delegate.directories = ['lib/assets/i18n'];

    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => ChatNotificationService(),
        ),
        ChangeNotifierProvider(
          create: (_) => AuthUseCase(),
        ),
        ChangeNotifierProvider(
          create: (context) => AuthViewModel(
            AuthUseCase(),
            context,
          ),
        ),
      ],
      child: MaterialApp.router(
        theme: ThemeData(
            fontFamily: 'Lato',
            colorScheme: ColorScheme.fromSwatch().copyWith(
              primary: const Color(0xFF0096C7),
              secondary: Colors.orange.shade700,
              tertiary: Colors.white,
              outline: Colors.grey,
            )),
        debugShowCheckedModeBanner: false,
        scrollBehavior: AppScrollBehavior(),
        title: 'app_name'.i18n(),
        localizationsDelegates: [
          GlobalMaterialLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          LocalJsonLocalization.delegate
        ],
        supportedLocales: const [
          Locale('pt', 'BR'),
          Locale('en', 'US'),
        ],
        routerConfig: Modular.routerConfig,
      ),
    );
  }
}

// AuthViewModel.dart
class AuthViewModel extends ChangeNotifier {
  final AuthUseCase _authUseCase;
  final BuildContext context;

  AuthViewModel(this._authUseCase, this.context);

  Future<void> login(String email, String password) async {
    try {
      _isLoading = true;
      notifyListeners();

      final errorMessage = await _authUseCase.login(email, password);

      if (errorMessage != null) {
        _showErrorDialog(errorMessage);
      } else {
        Modular.to.navigate('/home/');
      }
    } on AuthException catch (error) {
      _handleAuthException(error);
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }
  
  void _showErrorDialog(String msg) {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text('error_occurred'.i18n()),
        content: Text(msg),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('close'.i18n()),
          ),
        ],
      ),
    );
  }
}

// LoginScreen.dart
Future<void> _submit() async {
  final isValid = _formKey.currentState?.validate() ?? false;

  if (!isValid) {
    return;
  }

  _formKey.currentState?.save();

  AuthViewModel authViewModel =
      Provider.of<AuthViewModel>(context, listen: false);

  await authViewModel.login(
    _formData.email,
    _formData.password,
  );
}

尽管 AppWidget 中包含了 MaterialApp,但在尝试从 AuthViewModel 显示对话框时,我仍然遇到与缺少 MaterialApp 祖先相关的错误。

有人可以帮助我理解为什么会发生此错误以及如何在使用 MultiProvider 和 ModularApp 设置时正确显示对话框?我检查了我的代码,我相信我有必要的 MaterialApp 包装我的 AppWidget,但错误仍然存在。

我得到的错误是这样的:

E/RecaptchaCallWrapper( 4976): Initial task failed for action RecaptchaAction(action=signUpPassword)with exception - The email address is badly formatted.
D/InsetsController( 4976): show(ime(), fromIme=true)
E/flutter ( 4976): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: No MaterialLocalizations found.
E/flutter ( 4976): _InheritedProviderScope<AuthViewModel?> widgets require MaterialLocalizations to be provided by a Localizations widget ancestor.
E/flutter ( 4976): The material library uses Localizations to generate messages, labels, and abbreviations.
E/flutter ( 4976): To introduce a MaterialLocalizations, either use a MaterialApp at the root of your application to include them automatically, or add a Localization widget with a MaterialLocalizations delegate.
E/flutter ( 4976): The specific widget that could not find a MaterialLocalizations ancestor was:
E/flutter ( 4976):   _InheritedProviderScope<AuthViewModel?>
E/flutter ( 4976): The ancestors of this widget were:
E/flutter ( 4976):   ChangeNotifierProvider<AuthViewModel>
E/flutter ( 4976):   _NestedHook
E/flutter ( 4976):   _InheritedProviderScope<AuthUseCase?>
E/flutter ( 4976):   ChangeNotifierProvider<AuthUseCase>
E/flutter ( 4976):   _NestedHook
E/flutter ( 4976):   _InheritedProviderScope<ChatNotificationService?>
E/flutter ( 4976):   ChangeNotifierProvider<ChatNotificationService>
E/flutter ( 4976):   _NestedHook
E/flutter ( 4976):   MultiProvider
E/flutter ( 4976):   AppWidget
E/flutter ( 4976):   _ModularInherited
E/flutter ( 4976):   ModularApp
E/flutter ( 4976):   MediaQuery
E/flutter ( 4976):   _MediaQueryFromView
E/flutter ( 4976):   _ViewScope
E/flutter ( 4976):   View-[GlobalObjectKey FlutterView#70e35]
E/flutter ( 4976):   [root]
E/flutter ( 4976): #0      debugCheckHasMaterialLocalizations.<anonymous closure> (package:flutter/src/material/debug.dart:93:7)
E/flutter ( 4976): #1      debugCheckHasMaterialLocalizations (package:flutter/src/material/debug.dart:113:4)
E/flutter ( 4976): #2      showDialog (package:flutter/src/material/dialog.dart:1287:10)
E/flutter ( 4976): #3      AuthViewModel._showErrorDialog (package:estudo/src/feature/auth/viewmodel/auth_view_model.dart:82:5)
flutter dialog provider materialapp
1个回答
0
投票

根据错误,您的 AuthViewModel 显示的对话框需要 MaterialLocalizations,但您用来显示对话框的提供程序上下文没有提供这些本地化的必要祖先小部件。

使用此代码使其正确 -

class AuthViewModel extends ChangeNotifier {
  final AuthUseCase _authUseCase;
  final BuildContext appContext; // Add this line

  AuthViewModel(this._authUseCase, this.appContext);



  void _showErrorDialog(String msg) {
    showDialog(
      context: appContext, // Use appContext instead of context
      builder: (ctx) => AlertDialog(
        title: Text('error_occurred'.i18n()),
        content: Text(msg),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(),
            child: Text('close'.i18n()),
          ),
        ],
      ),
    );
  }
}

在 AppWidget 的构建方法中,当您创建 AuthViewModel 时,将 BuildContext 传递给它

ChangeNotifierProvider(
  create: (context) => AuthViewModel(
    AuthUseCase(),
    context, // Pass the context here
  ),
),

我希望您的错误能够得到解决,如果您遇到任何问题,请告诉我

© www.soinside.com 2019 - 2024. All rights reserved.