gpt4 book ai didi

Flutter - 将 GetIt 与 BuildContext 结合使用

转载 作者:行者123 更新时间:2023-12-05 02:50:27 32 4
gpt4 key购买 nike

我正在根据 flutter 文档在我的应用中使用本地化。
看这里: https://flutter.dev/docs/development/accessibility-and-localization/internationalization

我使用 get_it 包(版本 4.0.4)来检索单例对象,例如本地化委托(delegate)。不幸的是它需要一个 BuildContext属性(property)。有时在我的应用程序中我没有上下文引用,所以如果它能像这样工作就好了:GetIt.I<AppLocalizations>()而不是这个:AppLocalizations.of(context) .如果您像这样设置 get_it,它仍然可以毫无问题地实现:GetIt.I.registerLazySingleton(() => AppLocalizations.of(context));问题是您至少需要一次上下文才能使其工作。此外,如果您想在初始路径中立即显示本地化文本,则很难获得正确初始化的 BuildContext在您需要的时候。

我有点难以正确解释它,所以我在一个最小的例子中重现了这个问题。

我注释掉了一些会导致编译时错误的代码,但它显示了我想象的完成方式。

ma​​in.dart

GetIt getIt = GetIt.instance;

void setupGetIt() {
// How to get BuildContext properly if no context is available yet?
// Compile time error.
// getIt.registerLazySingleton(() => AppLocalizations.of(context));
}

void main() {
setupGetIt();

runApp(MyApp());
}

class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);

@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
// The above line also won't work. It has BuildContext but Applocalizations.of(context) won't work
// because it's above in the Widget tree and not yet setted up.
getIt.registerLazySingleton(() => AppLocalizations.of(context));
return MaterialApp(
supportedLocales: const [
Locale('en', 'US'),
Locale('hu', 'HU'),
],
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
localeResolutionCallback: (locale, supportedLocales) {
// check if locale is supported
for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode &&
supportedLocale.countryCode == locale?.countryCode) {
return supportedLocale;
}
}
// if locale is not supported then return the first (default) one
return supportedLocales.first;
},
// You may pass the BuildContext here for Page1 in it's constructor
// but in a more advanced routing case it's not a maintanable solution.
home: Page1(),
);
}
}

初始路线

class PageBase extends StatelessWidget {
final String title;
final Widget content;

PageBase(this.title, this.content);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: content,
);
}
}

class Page1 extends PageBase {
// It won't run because I need the context but clearly I don't have it.
// And in a real app you also don't want to pass the context all over the place
if you have many routes to manage.
Page1(String title)
: super(AppLocalizations.of(context).title, Center(child: Text('Hello')));

// Intended solution
// I don't know how to properly initialize getIt AppLocalizations singleton by the time
// it tries to retrieve it
Page1.withGetIt(String title)
: super(getIt<AppLocalizations>().title, Center(child: Text('Hello')));
}

locales.dart

String globalLocaleName;

class AppLocalizations {
//AppLocalizations(this.localeName);

static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}

static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();

static Future<AppLocalizations> load(Locale locale) async {
final String name =
locale.countryCode.isEmpty ? locale.languageCode : locale.toString();

final String localeName = Intl.canonicalizedLocale(name);

return initializeMessages(localeName).then((_) {
globalLocaleName = localeName;
return AppLocalizations();
});
}

String get title => Intl.message(
'This is the title.',
name: 'title',
);
}

class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const _AppLocalizationsDelegate();

@override
bool isSupported(Locale locale) {
return ['en', 'hu'].contains(locale.languageCode);
}

@override
Future<AppLocalizations> load(Locale locale) => AppLocalizations.load(locale);

@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}

还有一些intl生成的dart代码和.arb文件不是很重要,说明问题。


所以总而言之,我怎样才能使用我的 AppLocalizations例如在这种情况下,不使用上下文就将其分类为单例?也许我最初的方法不好,可以通过我所代表的其他方式来完成。如果您有解决方案,请告诉我。

谢谢。

最佳答案

要实现您所描述的内容,您需要首先使用 get_it 创建导航服务。按照以下步骤实现结果:

<强>1。创建导航服务

import 'package:flutter/material.dart';

class NavigationService {
final GlobalKey<NavigatorState> navigatorKey =
new GlobalKey<NavigatorState>();

Future<dynamic> navigateTo(String routeName) {
return navigatorKey.currentState!
.push(routeName);
}

goBack() {
return navigatorKey.currentState!.pop();
}
}

这使您可以在整个应用程序中从任何位置导航到任何位置,而无需构建上下文。您可以使用此导航器键来实现当前上下文的 AppLocalization 实例。有关这种无需构建上下文的导航方法,请参阅 FilledStacks 教程。

https://www.filledstacks.com/post/navigate-without-build-context-in-flutter-using-a-navigation-service/

<强>2。注册

GetIt locator = GetIt.instance;

void setupLocator() {
...
locator.registerLazySingleton(() => NavigationService());
...
}

3.在 Material 应用中分配导航键

return MaterialApp(
...
navigatorKey: navigationService.navigatorKey,
...
),

3.为 AppLocalizations 创建一个实例并将其导入到您想要使用的任何地方

localeInstance() => AppLocalizations.of(locator<NavigationService>().navigatorKey.currentContext!)!;

3.实际用例

import 'package:{your_app_name}/{location_to_this_instace}/{file_name}.dart';

localeInstance().your_localization_variable

关于Flutter - 将 GetIt 与 BuildContext 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63671225/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com