IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    How the GetX easy to use in Flutter

    Winson发表于 2023-12-11 02:44:28
    love 0

    1. Introduction

    Flutter is a powerful and cross-platform mobile app development framework, it’s easy to learn and build a nice user interface. But, if you are an experienced c#/Java programmer (it’s me~ ha ha), maybe you will be a little uncomfortable, because Flutter is a reactive programming framework, reactive programming is a declarative programming paradigm that is based on the idea of asynchronous event processing and data streams.

    So, if you want to update the UI in Flutter, you need to update the state to refresh the layout, the programming logics will be difference with C# or Java, so luckily there are many state management frameworks to help to do that, but these frameworks are not easy to understand and use except GetX.

    GetX is a fast, stable, and light state management library in flutter. There are so many State Management libraries in flutter like MobX, BLoC, Redux, Provider, etc. GetX is also a powerful micro framework and using this, we can manage states, make routing, and can perform dependency injection.

    2. Why Getx

    GetX is focused on performance and minimum consumption of resources. One of the key performance advantages of GetX lies in its minimal overhead. By minimizing unnecessary re-renders and widget rebuilds, GetX significantly reduces the computational burden on your application, resulting in faster rendering and improved overall performance.

    In addition, GetX leverages the power of efficient dependency injection. Its lightweight dependency injection mechanism enables the creation and management of dependencies without compromising performance. By efficiently managing dependencies, GetX helps eliminate unnecessary object instantiations and ensures efficient memory utilization.

    3. Base Usages

    3.1 Installing

    Add Get to your pubspec.yaml:

    dependencies:
        get: 4.6.6
    

    and import the lib in your dart file

    import 'package:get/get.dart';
    

    3.2 State Management

    GetX is really easy to use, for example, you can define a variable with .obs to make it observable

    var isEnabled = false.obs;
    
    ...
    
    //change to enable
    isEnabled.value = true;
    

    and use Obx(() => ) in UI to monitor the changes

    return Scaffold(
          appBar: AppBar(
            title: const Text('Test'),
            centerTitle: true,
          ),
          body: Stack(
            children: [
              Obx(
                () => controller.isEnabled.value 
                    ? ListView(
                        children: <Widget>[
                         ...
                        ],
                      )
                    : const SizedBox.shrink(),
              ),
            ],
          ), 
        );
      }
    

    for the above example, if the isEnabled value changed to true, then will show the ListView data, just so ease, right?

    3.3 Route Management

    Navigation is very important in an App, GetX can help you easy to manage it. For example:

    //navigate to a next page
    Get.to(NextPage());
    
    //navigate to next page by name
    Get.tonamed('/next');
    
    //beck to previous page or close snackbar,dialogs...
    Get.back();
    
    //to go to the next page and no option to go back to the previous page (for use in SplashPage, login Page, etc.)
    Get.off(NextPage());
    
    //to go to the next screen and cancel all previous routes (useful in shopping carts, polls, and tests)
    Get.offAll(NextPage());
    

    Ok, you can find more detail usages in the official project website, and I will show another tips what I am using 🙂

    4. Other Usages

    4.1 Using in bottomNavigationBar

    Most of times, we just need to bind the dependencies in main.dart when startup the app, but if you are using the bottomNavigationBar, you also need to bind the dependence in the bottom navigation main page, for example the below structure

    dashboard (bottomNavigationBar main page)
        -- home
            -- product1
                -- product1_detail
            -- product2
                -- product1_detail
        -- settings
    

    so the bindings in dashboard should be like below

    class DashboardBinding extends Bindings {
      @override
      void dependencies() {
        Get.lazyPut<DashboardController>(
          () => DashboardController(),
        );
        Get.lazyPut<HomeController>(
          () => HomeController(),
        );
        Get.lazyPut<Product1Controller>(
          () => Product1Controller(),
        );
        Get.lazyPut<Product2Controller>(
          () => Product2Controller(),
        );
      }
    }
    

    and when you want to navigate to the product1 detail page from product1, you need to add the binding before to go

    return InkWell(
    onTap: () {
      Get.lazyPut<Product1DetailController>(
        () => Product1DetailController(),
      );
      Get.to(() => const Product1DetailPage());
    },
    

    4.2 Using service for the common functions

    GetX Service useful to let you make some common functions, you can handle the same lifecycle (onInit(), onReady(), onClose()) as controller, and you can get the service anywhere with Get.find(). For example, create a local storage service for handle the SharedPreferences functions

    class LocalStorageService extends GetxService {
    Future<T?> getValue<T>(
        LocalStorageKeys key, [
        T Function(Map<String, dynamic>)? fromJson,
      ]) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        switch (T) {
          case int:
            return prefs.getInt(key.name) as T?;
          case double:
            return prefs.getDouble(key.name) as T?;
          case String:
            return prefs.getString(key.name) as T?;
          case bool:
            return prefs.getBool(key.name) as T?;
          default:
            assert(fromJson != null, 'fromJson must be provided for Object values');
            if (fromJson != null) {
              final stringObject = prefs.getString(key.name);
              if (stringObject == null) return null;
              final jsonObject = jsonDecode(stringObject) as Map<String, dynamic>;
              return fromJson(jsonObject);
            }
        }
        return null;
      }
    
      void setValue<T>(LocalStorageKeys key, T value) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        switch (T) {
          case int:
            prefs.setInt(key.name, value as int);
            break;
          case double:
            prefs.setDouble(key.name, value as double);
            break;
          case String:
            prefs.setString(key.name, value as String);
            break;
          case bool:
            prefs.setBool(key.name, value as bool);
            break;
          default:
            assert(
              value is Map<String, dynamic>,
              'value must be int, double, String, bool or Map<String, dynamic>',
            );
            final stringObject = jsonEncode(value);
            prefs.setString(key.name, stringObject);
        }
      }
    }
    

    and init the service in main.dart

    Get.put(LocalStorageService());
    

    then you can use it in anywhere (include in other services)

    //get the service
    var localStorage = Get.find<LocalStorageService>();
    
    ...
    
    //save the value
    localStorage.setValue<String>('currentLanguage', 'en');
    
    //get the value
    var currentLanguage =
          await localStorage.getValue<String>('currentLanguage');
    

    4.3 Using the dialog

    GetX support to use the popup dialog, you can easy to use the default dialog in as below

    Get.defaultDialog(
        title: 'Title',
        titleStyle: const TextStyle(color: Colors.red),
        middleText: 'Messages');
    

    This is only the normal alert dialog, if you want to use a custom style, you can use below

    Get.dialog(
      Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 40),
            child: Container(
              decoration: const BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.all(
                  Radius.circular(20),
                ),
              ),
              child: Padding(
                padding: const EdgeInsets.all(20.0),
                child: Material(
                  child: 
    
                  //your layout widgets
    
                ),
              ),
            ),
          ),
        ],
      ),
    );
    

    as you can see, you can put any widgets in Get.dialog(), so this is not only a dialog but also a popup page 🙂

    and you can create the dialog as a service, there is a complete custom dialog service below:

    enum DialogType {
      info,
      success,
      error,
      warning,
    }
    
    
    class DialogService extends GetxService {
      showAlert(
        String title,
        String message, {
        DialogType dialogType = DialogType.info,
        Function? callback,
      }) {
        IconData iconData = Icons.info;
        Color iconColor = Colors.blueGrey;
        if (dialogType == DialogType.error) {
          iconData = Icons.error;
          iconColor = Colors.red;
        } else if (dialogType == DialogType.warning) {
          iconData = Icons.warning;
          iconColor = Colors.yellow;
        } else if (dialogType == DialogType.success) {
          iconData = Icons.done_rounded;
          iconColor = Colors.green;
        }
    
        Get.dialog(
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 40),
                child: Container(
                  decoration: const BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.all(
                      Radius.circular(20),
                    ),
                  ),
                  child: Padding(
                    padding: const EdgeInsets.all(20.0),
                    child: Material(
                      child: Column(
                        children: [
                          const SizedBox(height: 10),
                          Icon(
                            iconData,
                            color: iconColor,
                            size: 50,
                          ),
                          const SizedBox(height: 10),
                          Text(
                            title,
                            style: const TextStyle(
                                fontSize: 24, fontWeight: FontWeight.bold),
                            textAlign: TextAlign.center,
                          ),
                          const SizedBox(height: 20),
                          Text(
                            message,
                            style: const TextStyle(fontSize: 18),
                            textAlign: TextAlign.center,
                          ),
                          const SizedBox(height: 50),
                          //Buttons
                          Row(
                            children: [
                              Expanded(
                                child: ElevatedButton(
                                  style: ElevatedButton.styleFrom(
                                    foregroundColor: const Color(0xFFFFFFFF),
                                    backgroundColor: Colors.blue,
                                    minimumSize: const Size(0, 45),
                                    shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(8),
                                    ),
                                  ),
                                  onPressed: () {
                                    callback != null ? callback() : null;
                                  },
                                  child: Text(
                                    style: const TextStyle(fontSize: 18),
                                    LabelKeys.ok.tr,
                                  ),
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    you can use it anywhere

    final dialog = Get.find<DialogService>();
    
    
    //show the normal alert
    dialog.showAlert(
      'Title',
      'This is a normal info alert'
    );
    
    //show the error alert
    dialog.showAlert(
      'Error',
      'This is an error alert',
      dialogType: DialogType.error
    );
    

    5. Advanced Apis

    There are also many advanced APIs can be use, such like

    // give the current args from currentScreen
    Get.arguments
    
    // give name of previous route
    Get.previousRoute
    
    // give the raw route to access for example, rawRoute.isFirst()
    Get.rawRoute
    
    // give access to Routing API from GetObserver
    Get.routing
    
    // check if snackbar is open
    Get.isSnackbarOpen
    
    // check if dialog is open
    Get.isDialogOpen
    
    // check if bottomsheet is open
    Get.isBottomSheetOpen
    
    //Check in what platform the app is running
    GetPlatform.isAndroid
    GetPlatform.isIOS
    GetPlatform.isMacOS
    GetPlatform.isWindows
    GetPlatform.isLinux
    GetPlatform.isFuchsia
    
    //Check the device type
    GetPlatform.isMobile
    GetPlatform.isDesktop
    //All platforms are supported independently in web!
    //You can tell if you are running inside a browser
    //on Windows, iOS, OSX, Android, etc.
    GetPlatform.isWeb
    
    
    // Equivalent to : MediaQuery.of(context).size.height,
    // but immutable.
    Get.height
    Get.width
    
    // Gives the current context of the Navigator.
    Get.context
    
    // Gives the context of the snackbar/dialog/bottomsheet in the foreground, anywhere in your code.
    Get.contextOverlay
    
    ...
    

    you can find more in here

    6. Conclusion

    GetX is powerful, it’s save my many times, and it’s easy to understand, it also has a highly active and helpful community, you can find the solutions in their community if there are any problems, and you also can install the vs-code extension to help to build the GetX project. Please let me know if you have another opinions of GetX 🙂

    Loading

    The post How the GetX easy to use in Flutter first appeared on Coder Blog.



沪ICP备19023445号-2号
友情链接