GetX快速上手

GetX是一个状态管理插件,不仅有状态管理功能,还有路由管理、主题管理多语言、Obx局部更新、网络请求、数据验证等功能,可以作为基本框架使用了。

GetX的三个原则:

  • 性能
  • 效率
  • 结构

GetX仅会编译你使用到的功能,没用到的功能不会编译到代码中。他的众多功能都在独立的容器中,只有使用了才会启动。

本来想先写一个Flutter的快速上手再来写GetX来着,但是整理了一下感觉Flutter的内容还是有些多,所以把Flutter的内容先网后放一放,直接记录一下GetX

因此,阅读本篇之前,要有Flutter基础哦。

GetX的三大主要功能:

  • 状态管理
  • 路由管理
  • 依赖管理

要使用GetX的一些功能时要在根节点包装为GetMaterialApp

如果你只用Get来进行状态管理或依赖管理,就没有必要使用GetMaterialAppGetMaterialApp对于路由、snackbar、国际化、bottomSheet、对话框以及与路由相关的高级apis和没有上下文(context)的情况下是必要的。

状态管理

GetX里边的状态本质都是Streams

声明响应式变量

  1. 使用Rx{Type}
1
2
3
4
final name = RxString('');
final. isLogged = RxBool(false);
final items = RxList<String>([]);
final myMap = RxMap<String, int>({});
  1. 使用Rx并规定范型Rx<Type>
1
2
3
4
final name = Rx<String>('');
final isLogged = Rx<Bool>(false);
final items = Rx<List<String>>([]);
final myMap = Rx<Map<String, int>>({});
  1. 添加.obs作为value的属性
1
2
3
4
final name = ''.obs;
final isLogged = alse.obs;
final items = <String>[].obs;
final myMap = <String, int>{}.obs;

Dart现在注重空安全, 所以总是用一个初始值来开始变量。

在变量的末尾添加.obs使其变成可观察到变量,它的.value就是初始值。

List是完全可观察的,在List中不需要使用.value。不过像String, int这些原始类型不能被扩展,需要强制使用.value,当然可以使用getter/setter来封装处理这些类型。

UI中显示该值并在变化时更新页面,只需要:

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

使用GetX,一般来说不再需要使用StatefulWidget了。

路由管理

导航到新页面

1
Get.to(NextScreen());

用别名导航到新页面

1
Get.toNamed('/details');

要关闭snackbars, dialogs, bottomsheets或任何你通常会用Navigator.pop(context)关闭的东西。

1
Get.back();

进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)。

1
Get.off(NextScreen());

进入下一个页面并取消之前的所有路由(在购物车、投票和测试中很有用)

1
Get.offAll(NextScreen());

别名路由浏览并删除前一个页面。

1
Get.offNamed("/NextScreen");

别名路由浏览并删除所有以前的页面。

1
Get.offAllNamed("/NextScreen");

要导航到下一条路由,并在返回后立即接收或更新数据。

1
var data = await Get.to(Payment());

在另一个页面上,发送前一个路由的数据。

1
Get.back(result: 'success');

并使用它,例:

1
if(data == 'success') madeAnything();

如果你要在没有context的情况下使用路由/SnackBars/Dialogs/BottomSheets,或者使用高级的Get API,你需要使用GetMaterialApp

要定义路由,使用GetMaterialApp。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
// 定义路由
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.zoom
),
],
)
);
}

要处理到未定义路线的导航(404错误),可以在GetMaterialApp中定义unknownRoute页面

1
2
3
4
5
6
7
8
9
10
11
12
void main() {
runApp(
GetMaterialApp(
unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
],
)
);
}

发送数据到别名路由只要发送想要的参数即可,这里可以接受任何东西:

1
Get.toNamed("/NextScreen", arguments: 'Get is the best');

在类/控制器上可以接受:

1
print(Get.arguments);

Get提供高级动态URL,就像在Web上一样。Web开发者可能已经在Flutter上想要这个功能了,Get也解决了这个问题

1
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");

在你的controller/bloc/stateful/stateless类上:

1
2
3
4
print(Get.parameters['id']);
// out: 354
print(Get.parameters['name']);
// out: Enzo

你也可以用Get轻松接收NamedParameters。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => MyHomePage(),
),
GetPage(
name: '/profile/',
page: () => MyProfile(),
),
//你可以为有参数的路由定义一个不同的页面,也可以为没有参数的路由定义一个不同的页面,但是你必须在不接收参数的路由上使用斜杠"/",就像上面说的那样。
GetPage(
name: '/profile/:user',
page: () => UserProfile(),
),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.cupertino
),
],
)
);
}

发送别名路由数据

1
Get.toNamed("/profile/34954");

在第二个页面上,通过参数获取数据

1
2
print(Get.parameters['user']);
// out: 34954

或像这样发送多个参数

1
Get.toNamed("/profile/34954?flag=true");

在第二个屏幕上,通常按参数获取数据

1
2
3
print(Get.parameters['user']);
print(Get.parameters['flag']);
// out: 34954 true

依赖管理

Get有一个简单而强大的依赖管理器,它允许你只用1行代码就能检索到与你的Bloc或Controller相同的类,无需Provider context,无需inheritedWidget。

1
Controller controller = Get.put(Controller());

Get.put(): 最常见的插入依赖关系的方式

1
2
3
Get.put<SomeClass>(SomeClass());
Get.put<LoginController>(LoginController(), permanent: true);
Get.put<ListItemController>(ListItemController, tag: "some unique string");

Get.lazyPut: 可以懒加载一个依赖,这样它只有在使用时才会被实例化。这对于计算代价高的类来说非常有用

1
2
3
4
5
6
7
8
9
10
11
12
13
///只有当第一次使用Get.find<ApiMock>时,ApiMock才会被调用。
Get.lazyPut<ApiMock>(() => ApiMock());

Get.lazyPut<FirebaseAuth>(
() {
// ... some logic if needed
return FirebaseAuth();
},
tag: Math.random().toString(),
fenix: true
)

Get.lazyPut<Controller>( () => Controller() )

Get.putAsync: 如果你想注册一个异步实例,你可以使用

1
2
3
4
5
6
7
Get.putAsync<SharedPreferences>(() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('counter', 12345);
return prefs;
});

Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )

Get.find(): 会找到你的控制器,并将其提供给你。

1
2
3
final controller = Get.find<Controller>();
// 或者
Controller controller = Get.find();

GetX插件

GetX的使用比较简单,只在使用层面,也没有太多需要去通过示例来描述的,大家查看API文档即可。GetX推出了代码生成插件,非常好用,可以简单介绍一下:

Android Studio中通过GetX插件可以右键创建GetX代码。

常用功能一般有选择page/component,创建文件夹,生成前缀。

我们以默认配置生成的文件有三个,比如我们创建order

  • order_view.dart - 视图6
  • order_logic.dart - 逻辑
  • order_state.dart - 状态

使用方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// state中定义响应式变量
import 'package:get/get.dart';

class OrderState {
late RxInt age;
late RxString name;
OrderState() {
///Initialize variables
age = 20.obs;
name = 'sink'.obs;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
// logic中定义数据修改逻辑
import 'package:get/get.dart';

import 'order_state.dart';

class OrderLogic extends GetxController {
final OrderState state = OrderState();

void increment() {
state.age ++;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// view中渲染UI并使用状态
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'order_logic.dart';

class OrderPage extends StatelessWidget {
OrderPage({Key? key}) : super(key: key);

final logic = Get.put(OrderLogic());
final state = Get.find<OrderLogic>().state;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Order'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text('${state.name} - ${state.age}')),
ElevatedButton(
onPressed: () {
logic.increment();
},
child: const Text('age++'),
)
],
),
),
);
}
}

使用GetX插件可以大幅的提升效率,推荐使用哦

作者

胡兆磊

发布于

2024-04-03

更新于

2024-04-07

许可协议