Ric*_*cky 5 service-locator flutter
我根据 flutter 文档在我的应用程序中使用本地化。
请参阅此处: https://flutter.dev/docs/development/accessibility-and-localization/internationalization
我使用 get_it 包(版本 4.0.4)来检索单例对象,例如本地化委托。不幸的是它需要一个BuildContext属性。有时在我的应用程序中,我没有上下文引用,因此如果它像这样工作而GetIt.I<AppLocalizations>()不是这样:那就太好了AppLocalizations.of(context)。如果您像这样设置 get_it ,它仍然可以毫无问题地实现:GetIt.I.registerLazySingleton(() => AppLocalizations.of(context));问题是您至少需要上下文一次才能使其工作。此外,如果您想在初始路线中立即显示本地化文本,那么BuildContext在需要时正确初始化会更加困难。
对我来说正确解释它有点困难,所以我用一个最小的例子重新创建了这个问题。
我注释掉了一些会导致编译时错误的代码,但它显示了我想象的完成方式。
主程序.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(),
);
}
}
Run Code Online (Sandbox Code Playgroud)
初始路线
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')));
}
Run Code Online (Sandbox Code Playgroud)
语言环境.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;
}
Run Code Online (Sandbox Code Playgroud)
一些 intl 生成的 dart 代码和 .arb 文件对于说明问题来说并不是那么重要。
总而言之,AppLocalizations在这种情况下,我怎样才能在不使用上下文的情况下将我的类用作单例呢?也许我最初的方法不好,可以用我所代表的其他方式来完成。如果您有解决方案,请告诉我。
谢谢。
小智 0
您可以使用一些不可本地化的启动屏幕与FutureBuilder和getIt.allReady()。
就像是:
class SplashScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: getIt.allReady(),
builder: (context, snapshot) {
if (snapshot.hasData) {
// Navigate to main page (with replace)
} else if (snapshot.hasError) {
// Error handling
} else {
// Some pretty loading indicator
}
},
);
}
Run Code Online (Sandbox Code Playgroud)
我还想推荐用于处理 get_it 的可注入包。
| 归档时间: |
|
| 查看次数: |
8906 次 |
| 最近记录: |