美文网首页
flutter 国际化(Intl)初始化流程详解

flutter 国际化(Intl)初始化流程详解

作者: 晨曦中的花豹 | 来源:发表于2024-02-20 14:58 被阅读0次

flutter中常用的国际化是Intl,通常会生成这样的目录结构


image.png

然后在代码中的使用方式为

MaterialApp(
  localizationsDelegates: [S.delegate],
),
S.of(context).test;

看到of想必大家能联想起InheritedWidget,其实国际化本质就是依托于InheritedWidget
下面我们从后往前推,先看下S.of(context)

static S of(BuildContext context) {
    final instance = S.maybeOf(context);
    assert(instance != null,
        'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?');
    return instance!;
  }

  static S? maybeOf(BuildContext context) {
    return Localizations.of<S>(context, S);
  }

这里出现了Localizations

static T? of<T>(BuildContext context, Type type) {
    assert(context != null);
    assert(type != null);
    final _LocalizationsScope? scope = context.dependOnInheritedWidgetOfExactType<_LocalizationsScope>();
    return scope?.localizationsState.resourcesFor<T?>(type);
  }

然后是_LocalizationsScope,他是我们要找的InheritedWidget

image.png
所以,可想而知,我们的国家化的内容用该是通过这里获取
然后我们看看_LocalizationsScope是在哪里创建的
image.png
image.png
最终WidgetsApp就是在MaterialApp中创建的
通过上边的源代码发现,我们最初传入的[S.delegate]给到了Localizationsdelegates属性,而Localizationsstate,是赋值给了_LocalizationsScopelocalizationsState属性
所以此时思路应该清晰,Localizations负责管理所有的国际化,而_LocalizationsScope是负责国际化上下文的管理
这个时候我们返回头再看Localizations.of<S>(context, S)干了什么
image.png
image.png
继续寻找_typeToResources的来源
image.png
image.png

这里可以看到Localizationsdelegates最终转化成了_LocalizationsState_typeToResources,而_typeToResources是以国际化的类型与国际化的实例作为键值对的形式存储了起来

到此项目中使用国际化的详细流程就结束了

这里我们可以优化的一点是:如果是如果我们不想在使用的时候依托于上下文,来使用国际化,我们可以寻找一个恰当的时机来保存一个_LocalizationsScope创建之后的一个BuildContext,因为这个BuildContext足以通过上下文获取到国际化的内容,这就有很多种方式了,这列举一种:onGenerateTitle中的context
因为通过上下文

image.png
image.png
image.png
这里的title最终会到_LocalizationsScope下游,所以我们可以保存onGenerateTitle中的BuildContext
MaterialApp(
          onGenerateTitle: (BuildContext context) {
            globalContext = context;
            return "title";
          },
          localizationsDelegates: [S.delegate],
)

T getLanguage<T>() {
    final instance = Localizations.of<T>(globalContext, T);
    assert(instance != null, '没有找到${T}');
    return instance!;
}

在使用的时候,直接提供Type就可以了,实现了国际化与BuildContext树的解耦

getLanguage<S>().test;

相关文章

网友评论

      本文标题:flutter 国际化(Intl)初始化流程详解

      本文链接:https://www.haomeiwen.com/subject/diybadtx.html