Flutter GetX框架使用

1.GetX

GetX 是 Flutter 上的一个轻量强大的解决方案:高性能的状态管理、智能的依赖注入和便捷的路由管理

为什么选择 GetX?

  • 性能: 专注性能和最小资源消耗。
  • 效率: 语法简捷,并保持极高的性能。
  • 结构: 将界面、逻辑、依赖和路由完全解耦。

2.安装

1)将 Get 添加到pubspec.yaml文件中。

dependencies:
  get:

2)在需要用到的文件中导入。

import 'package:get/get.dart';

3.GetX的计数器示例

100多行(含注释) "计数器 "项目使用 GetX 重写只需 26 行代码(含注释)。

1) 在MaterialApp前添加 "Get",将其变成GetMaterialApp。

void () => runApp(GetMaterialApp(home: Home()));
  • GetMaterialApp预配置的封装型 Widget,可内置路由、依赖注入、国际化等关键配置。

2)创建业务逻辑类,并将所有的变量,方法和控制器放在里面。

class Controller extends GetxController{
  var count = 0.obs;
  increment() => count++;
}

3)创建界面,使用StatelessWidget节省一些内存。

class Home extends StatelessWidget {

  @override
  Widget build(context) {

    // 使用Get.put()实例化你的类,使其对当下的所有子路由可用。
    final Controller c = Get.put(Controller());

    return Scaffold(
      // 使用Obx(()=>每当改变计数时,就更新Text()。
      appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),

      // 用一个简单的Get.to()即可代替Navigator.push那8行,无需上下文!
      body: Center(child: ElevatedButton(
        child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
      floatingActionButton:
      FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
  }
}

class Other extends StatelessWidget {
  // 你可以让Get找到一个正在被其他页面使用的Controller,并将它返回给你。
  final Controller c = Get.find();

  @override
  Widget build(context){
    // 访问更新后的计数变量
    return Scaffold(body: Center(child: Text("${c.count}")));
  }
}

4.三大核心功能

状态管理

Get有两个不同的状态管理器:简单的状态管理器(GetBuilder)和响应式状态管理器(GetX)。

简单的状态管理器:需手动调用update()触发刷新。

响应式状态管理器

这就是你的计数变量。

var name = 'Jonatas Borges';

要想让它变得可观察,你只需要在它的末尾加上".obs"

var name = 'Jonatas Borges'.obs;

而在UI中,当你想显示该值并在值变化时更新页面,只需这样做。

Obx(() => Text("${controller.name}"));

声明响应式变量的方式

使用 Rx{Type}

final name = RxString('');

使用 Rx,规定泛型 Rx

final name = Rx('');

添加 .obs 作为value的属性

final name = ''.obs;

路由管理

1)在MaterialApp前加上 "Get",把它变成GetMaterialApp。

void main() {
  runApp(
    GetMaterialApp( // Before: MaterialApp(
      initialRoute: '/',
      getPages: [	// 定义路由
        GetPage(name: '/', page: () => MyHomePage()),
        GetPage(name: '/second', page: () => Second()),
        GetPage(
          name: '/third',
          page: () => Third(),
          transition: Transition.zoom  
        ),
      ],
    )
  );
}

2)常用方法

Get.to(NextScreen());			//导航到新页面
Get.toNamed('/second');		//用别名导航到新页面
Get.back();								//关闭页面
Get.off(NextScreen());		//进入下一个页面,但没有返回上一个页面的选项
Get.offAll(NextScreen());	//进入下一个页面并取消之前的所有路由

依赖管理

1)注入依赖

Controller controller = Get.put(Controller()); // 而不是 Controller controller = Controller();
  • Get.put(): 不使用控制器实例也会被创建
  • Get.lazyPut(): 懒加载方式创建实例,只有在使用时才创建
  • Get.putAsync(): Get.put() 的异步版版本
  • Get.create(): 每次使用都会创建一个新的实例

调用 Get.put()、Get.lazyPut()、Get.putAsync()、Get.create() 会创建一个新的依赖项,然后将它注册到依赖管理容器中。

2)获取依赖

final controller = Get.find();
// 或者
Controller controller = Get.find();

调用Get.find()方法时,GetX会根据指定的类型从依赖管理容器中查找对应的依赖项。如果找到,就返回这个依赖项;否则抛出一个异常。

5.GetView

由于在 Flutter 中,有时需要在不同的组件中访问和操作同一个控制器实例。为了避免在每个组件中都写一遍 Get.find()GetX 库提供了一个 GetView 中间件。

GetView 的主要功能是简化控制器的获取。当你创建一个继承自 GetView 的组件时,你只需要指定控制器的类型,然后就可以在组件中直接使用 controller 属性来访问控制器实例。

class CounterPage extends GetView {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter')),
      body: Center(
        child: Obx(() => Text('Count: ${controller.count}')),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: controller.increment,
      ),
    );
  }
}

class CounterController extends GetxController{
  var count = 0.obs;
  increment() => count++;
}

6.Bindings类

可以将路由、状态管理器和依赖管理器完全集成。 当一个路由从Stack中移除时,所有与它相关的控制器、变量和对象的实例都会从内存中移除。

1)创建一个类并实现Binding,重写 "dependencies"方法,然后插入你要在该路由上使用的所有类。

class HomeBinding implements Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => HomeController());
    Get.put(()=> Api());
  }
}

class DetailsBinding implements Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => DetailsController());
  }
}

2)getPages配置 Binding 来建立路由管理器、依赖关系和状态之间的连接。

  • 使用别名路由:
getPages: [
  GetPage(
    name: '/',
    page: () => HomeView(),
    binding: HomeBinding(),
  ),
  GetPage(
    name: '/details',
    page: () => DetailsView(),
    binding: DetailsBinding(),
  ),
];

通过Bindings可以使用Get的内存管理机制:

  • 导航进入新页面 (Get.to() / Get.toNamed())
    • 控制器创建:当页面跳转时,若该页面绑定的控制器尚未创建,GetX 会通过 Get.put()Binding 类自动初始化控制器实例。
    • 控制器存储:新页面的控制器会被关联到当前路由的上下文中,并保存在 GetX 的内部路由栈管理中。
  • 返回上一页 (Get.back())
    • 控制器销毁:当路由退出时(通过返回操作),GetX 自动触发与该路由关联的所有控制器的 onClose() 方法,并释放其内存。

7.生命周期

GetX 会自动管理 GetXController 的生命周期。当这个依赖项被创建时,GetX会调用它的 onInit() 和 onReady()方法;当这个依赖项被删除时,GetX 会调用它的 onClose() 方法。

class DemoController extends GetxController {
  @override
  void onInit() {}    // 初始化操作(如加载数据、监听流)
  @override
  void onReady() {}   // 此时 Widget 已渲染完成,适合执行需要依赖 UI 的逻辑(如弹窗、动画)
  @override
  void onClose() {}   // 控制器被销毁时调用,用于释放资源(如关闭流、取消订阅)
}

8.混合开发的GetX生命周期问题

背景:为了减少首次进入Flutter页面的延迟,通常采用预加载Flutter引擎的策略。当原生应用启动时,预先初始化Flutter引擎,这样当用户跳转到Flutter页面时,引擎已经就绪,页面加载更快。预加载引擎时,引擎会启动Dart虚拟机,执行默认的Dart入口代码。如果入口代码中已经绑定了某个Controller,比如使用GetX的依赖注入,那么引擎初始化时就会创建这些Controller实例。

  • Flutter页面间的路由跳转:
跳转second页面
-> 执行 Get.toNamed('/second');
-> 执行 SecondController onInit()
-> 执行 SecondController onReady()

关闭页面
-> 执行 Get.back();
-> 执行 SecondController onClose()
  • Flutter与原生的路由跳转:
App启动
-> 执行 HomeController onInit()
-> 执行 HomeController onReady()

由原生进入Flutter页面
-> 执行 FlutterActivity onCreate()
-> ...

由Flutter页面返回到原生
-> 执行 FlutterActivity onDestroy()

影响:由Flutter页面返回到原生时不会触发控制器的 onClose(),导致状态残留。

方法1)监听FlutterApp生命周期

AppLifecycleListener 监听“原生到Flutter”、“Flutter到原生”两种状态:“原生到Flutter”时刷新UI;Flutter到原生”时进行状态重置。

late final AppLifecycleListener _listener;
var isFirstEnter = true;

_listener = AppLifecycleListener(
  onDetach: _onDetach,	//App可能还存有Flutter Engine,但视图并不存在
  onResume: _onResume,	//App具有输入焦点且可见的正在运行的状态
  onRestart: _onRestart,//后台到前台
  onPause: _onPause,		//前台到后台
);

void _onResume(){
  if (isFirstEnter) {
    _initState(); //UI刷新
    isFirstEnter = false;
  }
};
void _onDetach(){
  _resetState(); //状态重置
  isFirstEnter = true;
};
  • 优点:仅Flutter端修改。
  • 缺点:若 Flutter 页面被暂时隐藏(如跳转到其他原生页面),可能触发onDetach导致状态提前重置。

方法2)监听原生事件

使用MethodChannel监听原生事件,当FlutterActivity关闭(onDestroy)时,重置状态;FlutterActivity创建(onCreate)时,执行UI刷新。

// Flutter 端代码
class MainController extends GetxController {
  final MethodChannel _channel = MethodChannel('native_channel');

  @override
  void onInit() {
    _channel.setMethodCallHandler((call) async {
      if (call.method == 'onNativeDestroy') {
        // 重置控制器状态
        _resetState();
      } else if (call.method == 'onNativeCreate') {
        _initState();
      }
    });
  }
}
  • 优点:通过原生事件驱动控制器状态管理,避免状态提前重置的风险。
  • 缺点:Flutter与原生都需要修改。

参考链接

getx/README.zh-cn.md at master · jonataslaw/getx · GitHub

getx/documentation/zh_CN/state_management.md at master · jonataslaw/getx · GitHub

getx/documentation/zh_CN/route_management.md at master · jonataslaw/getx · GitHub

getx/documentation/zh_CN/dependency_management.md at master · jonataslaw/getx · GitHub

https://zhuanlan.zhihu.com/p/651402152

你可能感兴趣的:(flutter,android,java)