如何设置ChangeNotifier来加载区域设置文件

时间:2020-06-23 16:13:09

标签: flutter sharedpreferences future provider consumer

我是新来的人。

我正在构建一个多语言应用程序。

在应用启动之前,它需要加载当前的语言环境文件。 然后,每次用户更改语言环境时,都需要加载新文件。

至少在理论上,我认为可以使用“ ChangeNotifierProvider”,ProxyProvider或类似的方法来完成。

所以我让AppLanguage类根据语言代码加载正确的语言环境文件

class AppLanguage extends ChangeNotifier {

  String _appLocale = 'en';
  Map<String, String> _localizedStrings;

  Map<String, String> get localeData => this._localizedStrings;

  Future<bool> getLocaleData() async {
    var prefs = await SharedPreferences.getInstance();
    if (prefs.getString('language_code') == null) {
      _appLocale = 'en';
      await prefs.setString('language_code', _appLocale);
    } else {
      _appLocale = prefs.getString('language_code');
    }
    String jsonString = await rootBundle.loadString('i18n/$_appLocale.json');
    Map<String, dynamic> jsonMap = json.decode(jsonString);
    _localizedStrings = jsonMap.map((key, value) {
      return MapEntry(key, value.toString());
    });
    return true;
  }

  Future<void> changeLanguage(String locale) async {
    var prefs = await SharedPreferences.getInstance();
    _appLocale = locale;
    await prefs.setString('language_code', locale);
    notifyListeners();
  }
}

getLocaleData()函数读取数据并使用changeLanguage更改当前语言环境并触发notifyListeners

class Translator {

  final Map<String, String> localizedStrings;

  Translator(this.localizedStrings);

  String translate(String key) {
    return localizedStrings[key];
  }
}

小部件将使用翻译器类来获取正确的翻译。

我的问题是,如何将其连接到主电源。我被困在如何设置提供程序上。

void main() async {

  WidgetsFlutterBinding.ensureInitialized();

  AppLanguage appLanguage = AppLanguage();
  await appLanguage.getLocaleData();
  runApp(MyApp(appLanguage: appLanguage));
}

class MyApp extends StatelessWidget {
  final AppLanguage appLanguage;
  MyApp({this.appLanguage});

  @override
  Widget build(BuildContext context) {

    return MultiProvider(


      providers: [
        ProxyProvider<AppLanguage, Translator>(
          update: (context, appLanguage, trans) =>
              Translator(appLanguage.localeData),
        ),
      ],
      child: MaterialApp(
        title: 'Language Demo',
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Hello'),
      ),
      body: Container(),
    );
  }
}

有人可以帮忙吗? 还是提供一种更好的方法?

1 个答案:

答案 0 :(得分:0)

有些事情,ProxyProvider(或任何类型的ProxyProvider,ChangeNotifierProxyProvider等)在提供程序也依赖于更改时也会更新其值,但是您在main中创建了AppLanguage,没有注入依赖,就像一个简单的类一样(在上下文中并未真正提供),因此在这种情况下仅使用ChangeNotifierProvider会更容易。

有一个名为window.locale的参数,该参数返回当时使用的设备的语言,在应用程序启动时,您可以使用它来了解设备的语言(如果没有)。第一次使用sharedPreference。这样做的好处是,在您的示例中,如果未保存首选项,它将使用默认的“ en”作为英语,但是您还支持japanase,因此,如果有人将其设备安装为日语并首次下载您的应用,从一开始就很好用日语。

Future<Locale> _getLocaleData() async {
    var prefs = await SharedPreferences.getInstance();
    String languageCode = prefs.getString('language_code');
    if (languageCode  == null) {
      return window.locale;
    } else {
      return Locale(languageCode);
    }
}

void main() async {
  Locale locale = await _getLocaleData();
  runApp(MyApp(
    appLanguage: locale,
  ));
}

class MyApp extends StatelessWidget {
  final Locale language;

  MyApp({this.language});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<AppLanguage>(
      builder: (_) => AppLanguage(language),
      child: Consumer<AppLanguage>(builder: (context, model, _) {
        return MaterialApp(
          locale: model.appLocal,
          supportedLocales: [
            Locale('en', 'US'),
            Locale('ja', ''),
          ],
          localizationsDelegates: [
            AppLocalizations.delegate, //create your AppLocalizations just like the article you shared
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
          ],
          home: MyWidget(),
        );
      }),
    );
  }
}

class AppLanguage extends ChangeNotifier {

  AppLanguage(Locale locale) : _appLocale = locale;
  
  Locale _appLocale;
  Locale get appLocal => _appLocale;

  Future<void> changeLanguage(String locale) async {
    var prefs = await SharedPreferences.getInstance();
    _appLocale = Locale(locale);
    await prefs.setString('language_code', locale);
    notifyListeners();
  }
}