Flutter 每次不调用` of(context)`的本地化

Flutter 每次不调用` of(context)`的本地化,flutter,dart,Flutter,Dart,我发现定位程序使用起来很麻烦。要显示本地化字符串,我必须调用Localization.of(context).myAppTitle——在一个包含大量本地化字符串的大型嵌套小部件树中,这不是很流畅,也不容易浏览。更不用说它看起来很丑了 有没有办法让使用更方便?例如,我可以使用全局变量或带有本地化实例成员的静态类来简化访问吗?例如,声明顶级本地化变量 // Somewhere in the global scope Localization l; // main.dart class _MyAp

我发现定位程序使用起来很麻烦。要显示本地化字符串,我必须调用
Localization.of(context).myAppTitle
——在一个包含大量本地化字符串的大型嵌套小部件树中,这不是很流畅,也不容易浏览。更不用说它看起来很丑了

有没有办法让使用更方便?例如,我可以使用全局变量或带有
本地化
实例成员的静态类来简化访问吗?例如,声明顶级
本地化
变量

// Somewhere in the global scope
Localization l;


// main.dart
class _MyAppState extends State<MyApp>{

    @override
    void initState() {
        super.initState();
        getLocaleSomehow().then((locale){ 
            l = Localization(locale);
            setState((){}); 
        });
    }
}
所以从本质上说,我要问的是“不调用(上下文)
本地化的危险和/或缺点是什么?”

如果我真的需要使用(BuildContext)的
.of
方法来访问
本地化
实例,我至少可以将其存储在我的
状态小部件中吗?我在想

class DetailsPage extends StatefulWidget{
    Localization _l;

    @override
    Widget build(BuildContext context) {
        _l = Localization.of(context);

        // ... build widgets ...
    }
}

或者有没有其他方法可以使本地化变得不那么麻烦?

本地化
对象存储在
状态
中是完全可以的,在这种情况下效果非常好

如果只想让它看起来更漂亮,还可以在build方法中声明变量:

@覆盖
小部件构建(构建上下文){
最终l=本地化(上下文);
返回文本(l.myAppTitle);
}
StatefulWidget
中,您还可以在中重新分配变量,或者使用空感知
??=
运算符只分配一次,因为对象不会随时间而改变:

class\u MyStatefulWidgetState使用WidgetsBindingObserver扩展状态{
定位l;
@凌驾
didChangeDependencies(){
WidgetsBinding.instance.addObserver(这个);
l???=本地化(上下文);
super.didChangeDependencies();
}
@凌驾
无效区域设置(列表区域设置){
l=本地化(上下文);
super.didChangeLocales(locale);
}
@凌驾
处置{
WidgetsBinding.instance.removeObserver(此);
super.dispose();
}
@凌驾
小部件构建(BuildContext上下文)=>Text(l.myappite);
}
didChangeLocales
中,您可以每次重新分配。这确保变量始终保持适当的区域设置,并在第一次生成时初始化(使用
didChangeDependencies
)。请注意,我还包括了一个
WidgetsBindingObserver
,您需要按照代码所示处理它。

是的,它是必需的。 你可以解决这个问题,但这不是个好主意

原因是(
Localization.of(context,T)
可能会随着时间的推移而更新。它确实存在的一些情况是:

  • 地点改变了
  • 已异步加载获取的本地化数据包
  • MaterialApp/CupertinoApp更新了新的翻译版本

如果您没有正确地调用内部版本的
本地化,那么在这些情况下,您的UI可能无法正确更新。

您可以创建自己的文本小部件并在那里进行本地化。您可以用自己的MyText小部件替换所有文本小部件

class MyText extends StatelessWidget {
  String data;
  InlineSpan textSpan;
  TextStyle style;
  StrutStyle strutStyle;
  TextAlign textAlign;
  TextDirection textDirection;
  Locale locale;
  bool softWrap;
  TextOverflow overflow;
  double textScaleFactor;
  int maxLines;
  String semanticsLabel;
  TextWidthBasis textWidthBasis;

  MyText(
    this.data, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
  });

  @override
  Widget build(BuildContext context) {
    return Text(
      Localization.of(context).data,
      style: style,
      semanticsLabel: semanticsLabel,
      locale: locale,
      key: key,
      textAlign: textAlign,
      maxLines: maxLines,
      overflow: overflow,
      softWrap: softWrap,
      strutStyle: strutStyle,
      textDirection: textDirection,
      textScaleFactor: textScaleFactor,
      textWidthBasis: textWidthBasis,
    );
  }
}

谢谢,这正是我所怀疑的。但是,假设我不关心在用户更改设备区域设置时更改我的应用程序的语言(无需重新启动),是否仍然存在保留对
本地化
实例的全局引用的危险?毕竟,我敢打赌,大多数用户在第一次安装设备后不会改变他们的区域设置……是的。正如我所说,当异步加载翻译时,也需要这样做。谢谢!我注意到还有一个
didChangeLocales()
方法-使用它会比使用
didChangeDependencies()
更好吗?@MagnusW您可以同时使用这两种方法。我在回答中补充了我的意思。谢谢,我只是在考虑是不是应该做那样的事情:-)
class MyText extends StatelessWidget {
  String data;
  InlineSpan textSpan;
  TextStyle style;
  StrutStyle strutStyle;
  TextAlign textAlign;
  TextDirection textDirection;
  Locale locale;
  bool softWrap;
  TextOverflow overflow;
  double textScaleFactor;
  int maxLines;
  String semanticsLabel;
  TextWidthBasis textWidthBasis;

  MyText(
    this.data, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
  });

  @override
  Widget build(BuildContext context) {
    return Text(
      Localization.of(context).data,
      style: style,
      semanticsLabel: semanticsLabel,
      locale: locale,
      key: key,
      textAlign: textAlign,
      maxLines: maxLines,
      overflow: overflow,
      softWrap: softWrap,
      strutStyle: strutStyle,
      textDirection: textDirection,
      textScaleFactor: textScaleFactor,
      textWidthBasis: textWidthBasis,
    );
  }
}