# Guide to State Management in Flutter with GetX || Part - 2

In our previous article, we explored the basics of GetX and its core features. We discussed the introduction to GetX, demonstrated how to work with reactive state variables, explored dependency injection using GetX, and highlighted the advantages of using GetX over other state management libraries. If you missed any of these topics, please revisit the first part to build a solid foundation. Now, let’s take our understanding of GetX to the next level. In this article, we’ll delve deeper into advanced techniques, uncover hidden gems, and empower you to create robust and efficient Flutter applications using GetX.

## Syntax for Defining Named Routes Using GetX

1. First, make sure you’ve set up GetX in your app:
    
    * Install the `get` package by running:
        
        ```plaintext
        flutter pub add get
        ```
        
    * Import the library into your Dart code:
        
        ```dart
        import 'package:get/get.dart';
        ```
        
2. Replace `MaterialApp` with `GetMaterialApp` in your app’s main widget tree:
    
    ```dart
    GetMaterialApp(
      // Other properties...
      getPages: [
        GetPage(name: '/page-one', page: () => PageOne()),
        GetPage(name: '/page-two', page: () => PageTwo()),
        // Add more named routes as you needed
      ],
    )
    ```
    
3. Define your named routes using `GetPage`:
    
    * The `name` parameter specifies the route name (e.g., ‘/page-one’).
        
    * The `page` parameter is a callback that returns the widget for that route.
        

That’s it! You can now navigate to these named routes using `Get.toNamed('/page-one')` , `Get.toNamed('/page-two')` and so on.

---

## What is internationalisation in Flutter using GetX?

Internationalisation (often abbreviated as i18n) in Flutter refers to the process of adapting your app to support multiple languages and locales. It allows you to create a single codebase that can display content in different languages based on the user’s preferences. In the Context of GetX, a popular state management library for Flutter, you can achieve internationalisation efficiently using, the `Getx_Translator` package.

Here are the steps to set up internationalisation using `GetX_Translator`:

1. **Setting Up the Google Sheet for GetX\_Translator**:
    
    * Create a Google Sheet to serve as a centralised hub for all your application’s translations.
        
    * Define the structure of the sheet with headers for keys (used in your Flutter app) and columns for different languages.
        
    * Populate the sheet with localisation data, linking keys to their respective translations.
        
2. **Leveraging Google App Script for Communication**:
    
    * Use Google App Script to establish communication between the Google Sheet and your Flutter app.
        
    * Create a script for your sheet and paste the provided code in the script editor.
        
    * This script handles HTTP requests and manages the sheet’s data.
        

With this setup, managing translations becomes efficient and collaborative. You'll be able to dynamically switch between languages in your Flutter app based on user preferences.

---

## Some best practices for internationalisation in Flutter:

1. **Use** `intl` Package:
    
    * The `intl` package provides essential tools for formatting dates, numbers, and messages in different languages.
        
    * Leverage `intl` for date and number formatting, pluralisation, and message interpolation.
        
    * It supports various locales, so you can adapt your app to different regions seamlessly.
        
2. **Separate Texts from UI Widgets**:
    
    * Avoid hardcoding strings directly into UI widgets (e.g., `Text('Hello')`).
        
    * Instead, define your strings in a separate file (e.g., `strings.dart`) and reference them using keys.
        
    * This makes it easier to replace translations and maintain consistency.
        
3. **Choose a Localisation Strategy**:
    
    * Decide whether to use resource files (`.arb` or `.json`) or a centralised solution (like Google Sheets with `GetX_Translator`).
        
    * Resource files are straightforward but can become unwieldy for large apps.
        
    * Centralised solutions allow collaboration and dynamic updates but require additional setup.
        
4. **Test with Different Locales**:
    
    * Regularly test your app with different locales to ensure text fits within UI elements.
        
    * Pay attention to text expansion (some languages require more space) and right-to-left (RTL) layouts.
        
5. **Provide Context for Translators**:
    
    * When adding keys to your localisation files, include context information.
        
    * For example, instead of just `"Save"`, use `"buttonSave"` or `"actionSave"` to give translators context.
        
6. **Handle Plurals and Gender Variations**:
    
    * Different languages have varying rules for plurals and gender.
        
    * Use the `intl` package’s `Intl.plural` and `Intl.gender` methods to handle these variations.
        
7. **Localise Dates and Times**:
    
    * Use `DateFormat` from the `intl` package to format dates and times according to the user’s locale.
        
    * Be aware of different date formats (e.g., day-month-year vs. month-day-year).
        

Remember that internationalisation is an ongoing process. Regularly update your translations, test thoroughly, and consider user feedback to improve the localisation experience.

---

## How to Change theme using GetX in Flutter

1. **Create a Theme Controller**:
    
    * First, create a controller class (let’s call it `ThemeController`) that manages the theme state.
        
    * In this controller, define a boolean property (e.g., `isDarkMode`) to track whether the app is in dark mode or light mode.
        
2. **Toggle the Theme**:
    
    * Implement a method in `ThemeController` (e.g., `toggleDarkMode()`) that toggles the `isDarkMode` property.
        
    * Depending on the value of `isDarkMode`, switch between your light and dark theme data.
        
3. **Use GetX to Change the Theme**:
    
    * In your UI (e.g., `HomeScreen`), use `GetBuilder<ThemeController>` to listen for changes in the theme state.
        
    * Inside the `IconButton` (for toggling the theme), update the icon based on `isDarkMode`.
        
    * When the user taps the icon, call `controller.toggleDarkMode()` to switch the theme.
        
4. **Persist the Theme State**:
    
    * To make the theme persist across app restarts, use the `get_storage` package.
        
    * Create a helper class (e.g., `ThemeHelper`) that reads and writes the theme mode to local storage.
        
    * Save the theme mode when the user toggles it, and load it when the app starts.
        

Here’s a simplified example of how you can achieve this:

```dart
// ThemeController.dart
class ThemeController extends GetxController {
  bool isDarkMode = false;

  void toggleDarkMode() {
    isDarkMode = !isDarkMode;
    if (isDarkMode) {
      Get.changeTheme(themeDataDark);
    } else {
      Get.changeTheme(themeDataLight);
    }
    update();
  }
}
// main.dart
void main() async {
  await GetStorage.init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      theme: themeDataLight,
      darkTheme: themeDataDark,
      themeMode: ThemeHelper().theme,
      home: HomeScreen(),
    );
  }
}

// ThemeHelper.dart
class ThemeHelper {
  final _box = GetStorage();
  final _key = 'isDarkMode';

  ThemeMode get theme => _loadThemeFromBox() ? ThemeMode.dark : ThemeMode.light;

  bool _loadThemeFromBox() => _box.read(_key) ?? false;

  void switchTheme() {
    Get.changeThemeMode(_loadThemeFromBox() ? ThemeMode.light : ThemeMode.dark);
    _saveThemeToBox(!_loadThemeFromBox());
  }

  void _saveThemeToBox(bool isDarkMode) => _box.write(_key, isDarkMode);
}
```

Remember to adjust the theme data (`themeDataLight` and `themeDataDark`) according to your need for app’s design.

---

## Validation in Flutter using GetX

**Validation in Flutter using GetX** involves handling form input validation and displaying appropriate error messages. Let’s break it down:

1. **Create a Form Controller**:
    
    * Start by creating a controller (e.g., `FormController`) that manages form-related state.
        
    * Define observables for form fields (e.g., `RxString` for username, email, etc.).
        
    * Use `debounce` to validate input after a delay (e.g., 500 milliseconds) to avoid excessive validation calls.
        
2. **Implement Validation Logic**:
    
    * In the `validations` method, perform your validation checks (e.g., length, availability, etc.).
        
    * Update the `errorText` observable with validation errors or set it to `null` if validation passes.
        
    * Disable the submit button (`submitFunc`) during validation.
        
3. **UI Integration**:
    
    * In your UI (e.g., `FormObxPage`), use `Obx` to listen for changes in observables.
        
    * Bind the `onChanged` callback of `TextFormField` to the corresponding controller function (e.g., `usernameChanged`).
        
    * Enable/disable the submit button based on the `submitFunc` observable.
        

Here’s a simplified example:

```dart
class FormController extends GetxController {
  RxString username = RxString('');
  RxnString errorText = RxnString(null);
  Rxn<Function()> submitFunc = Rxn<Function()>(null);

  void usernameChanged(String val) {
    username.value = val;
  }

  void validations(String val) async {
    errorText.value = null; // Reset validation errors
    submitFunc.value = null; // Disable submit while validating

    if (val.isNotEmpty) {
      if (lengthOK(val) && await available(val)) {
        print('All validations passed, now enable submit button...');
        submitFunc.value = submitFunction();
        errorText.value = null;
      } else {
        errorText.value = 'please enter valid input'; // Set appropriate error message
      }
    }
  }
  // Other validation methods (lengthOK, available, etc.) go here
}

// UI Example
class FormObxPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    FormController fx = Get.put(FormController());

    return Scaffold(
      body: Column(
        children: [
          TextFormField(
            onChanged: fx.usernameChanged,
            decoration: InputDecoration(
              labelText: 'Username',
              errorText: fx.errorText.value,
            ),
          ),
          ElevatedButton(
            child: Text('Submit'),
            onPressed: fx.submitFunc.value,
          ),
        ],
      ),
    );
  }
}
```

> In conclusion, mastering state management in Flutter using GetX can significantly enhance the efficiency and robustness of your applications. By understanding advanced techniques such as defining named routes, implementing internationalisation, changing themes, and handling validation, you can create a seamless and dynamic user experience. Remember to follow best practices for internationalisation and persist theme states to ensure a consistent and user-friendly interface.

%%[linkedinwidget]
