Flutter: сохранение настроек языка и темы при использовании служебных функций GetX

Есть ли способ сохранить настройки пользователя (и получить их при перезагрузке) при использовании служебных функций GetX :

      Get.changeTheme(ThemeData().dark)

а также

      Get.updateLocale(Locale('en', 'US'));

Пока я могу изменить только и тему, и язык, но я не нашел в GetX способа сохранить какие-либо из моих изменений в каком-либо хранилище , чтобы их можно было загрузить при повторном открытии приложения в следующий раз. Я что-то не замечаю? Есть ли способ подключиться к процессу запуска и проверить некоторые сохраненные значения (например, в SharedPreferences) и передать их моему locale и theme свойства в GetMaterialApp?

Это мой код:

      import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      translations: Messages(),
      locale: Get.locale,
      theme: Get.theme,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
                onPressed: () => {
                      Get.changeTheme(
                          Get.isDarkMode ? ThemeData.light() : ThemeData.dark())
                    },
                child: Text('change_theme'.tr)),
            TextButton(
                onPressed: () => {
                      Get.updateLocale(Get.locale == Locale('en', 'US')
                          ? Locale('de', 'DE')
                          : Locale('en', 'US'))
                    },
                child: Text('change_language'.tr)),
          ],
        ));
  }
}

class Messages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'en_US': {
          'change_theme': 'Change Theme',
          'change_language': 'Change Language',
        },
        'de_DE': {
          'change_theme': 'Farbschema wechseln',
          'change_language': 'Sprache wechseln',
        }
      };
}

2 ответа

Это проще сделать с помощью GetStorage.

Если вы просто переходите со светлой темы на темную, нужно сохранять простой bool каждый раз, когда тема меняется.

Вот один из способов сделать это с помощью класса базовых настроек.

      class SettingsController extends GetxController {
  ThemeData themeData;

  final box = GetStorage();

  @override // called when you use Get.put before running app
  void onInit() {
    super.onInit();
    _restoreTheme();
  }

  void _restoreTheme() {
    bool isDark = box.read('isDark') ?? true; // null check for first time running this
    if (isDark) {
      themeData = ThemeData.dark();
    } else {
      themeData = ThemeData.light();
    }
  }

  void storeThemeSetting(bool isDark) {
    box.write('isDark', isDark);
  }
}

Переменная из SettingsControllerкласс инициализируется в зависимости от значения bool из хранилища. И это themeData file - это то, что вы передаете в свой, который выглядит так.

      class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final controller = Get.find<SettingsController>();
    return GetMaterialApp(
      theme: controller.themeData,
      title: 'Material App',
      home: StorageDemo(),
    );
  }
}

Затем поместите обе эти строки в свой метод Main перед запуском приложения.

        await GetStorage.init();

  Get.put(SettingsController());

Вот демонстрационная страница, где вы можете это проверить.

      class StorageDemo extends StatelessWidget {
  Widget build(BuildContext context) {
    final controller = Get.find<SettingsController>();
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            TextButton(
              onPressed: () {
                Get.changeTheme(ThemeData.dark());
                controller.storeThemeSetting(true);
              },
              child: Text('Dark Theme'),
            ),
            TextButton(
              onPressed: () {
                Get.changeTheme(ThemeData.light());
                controller.storeThemeSetting(false);
              },
              child: Text('Light Theme'),
            ),
          ],
        ),
      ),
    );
  }
}

Если у вас более сложный ThemeData файл, то применяется та же концепция, но вы должны хранить каждый цвет индивидуально, что, как я считаю, проще всего сделать, сохранив int значение цвета.

        int colorValue = Colors.red.value; // store this int

Тогда при восстановлении из хранилища вы можете использовать эту функцию

      Color mapIntToColor(int value) {
    return Color(value);
  }

Что касается ваших языковых настроек, то же самое. Просто добавьте переменную в свой класс Getx, сохраните пару строк, инициализируйте перед запуском приложения, затем передайте это Locale переменную в поле локали в GetMaterialApp.

Это должно быть возможно с использованием SharedPreferences. Назначьте пары ключ-значение (например, тема, темный) или (тема, светлый), которые вы можете сохранить и прочитать, а затем запустите свою логику для вызова ThemeData при открытии приложения.

экономия:

      _saveTheme() async {
  final prefs = await SharedPreferences.getInstance();
  final key = 'theme';
  final value = _theme;
  prefs.setString(key, value);
 }

чтение при инициализации приложения и установке темы - примерно так (не тестировал):

      _readTheme(context) async {
  final prefs = await SharedPreferences.getInstance();
  final key = 'theme';
  final _theme = prefs.getString(key) ?? "light"; //set theme to light if the key is not found in SharedPreferences
  Get.changeTheme(
   _theme == 'light' ? ThemeData.light() : ThemeData.dark())
}
Другие вопросы по тегам