Flutter Getx 状态管理
状态管理
目前,Flutter有几种状态管理器。但是,它们中的大多数都涉及到使用ChangeNotifier来更新widget,这对于中大型应用的性能来说是一个很糟糕的方法。你可以在Flutter的官方文档中查看到,ChangeNotifier应该使用1个或最多2个监听器,这使得它们实际上无法用于任何中等或大型应用。
Get 并不是比任何其他状态管理器更好或更差,而是说你应该分析这些要点以及下面的要点来选择只用Get,还是与其他状态管理器结合使用。
Get不是其他状态管理器的敌人,因为Get是一个微框架,而不仅仅是一个状态管理器,既可以单独使用,也可以与其他状态管理器结合使用。
Get有两个不同的状态管理器:响应式状态管理器、简单的状态管理器。
响应式状态管理器
- 响应式编程可能会让很多人感到陌生,因为它很复杂,但是GetX将响应式编程变得非常简单。
- 你不需要创建StreamControllers.
- 你不需要为每个变量创建一个StreamBuilder。
- 你不需要为每个状态创建一个类。
- 你不需要为一个初始值创建一个get。
- 使用 Get 的响应式编程就像使用 setState 一样简单。
- 让我们想象一下,你有一个名称变量,并且希望每次你改变它时,所有使用它的小组件都会自动刷新。
响应式状态管理器-计数器
让我们想象一下,你有一个名称变量,并且希望每次你改变它时,所有使用它的小组件都会自动刷新。
这就是你的计数变量。
int _counter = 0;
要想让它变得可观察,你只需要在它的末尾加上".obs"。
RxInt _counter = 0.obs;
而在UI中,当你想显示该值并在值变化时更新页面,只需这样做。
Obx(() => Text("$_counter"));
这就是全部,就这么简单。
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
RxInt _counter = 0.obs;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Gex 计数器"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Obx(() => Text("$_counter"))
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
_counter++;
},
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
声明一个响应式变量三种方式
第一种 使用 Rx{Type}
final name = RxString('');
final isLogged = RxBool(false);
final count = RxInt(0);
final balance = RxDouble(0.0);
final items = RxList<String>([]);
final myMap = RxMap<String, int>({});
第二种是使用 Rx,规定泛型 Rx。
final name = Rx<String>('');
final isLogged = Rx<Bool>(false);
final count = Rx<Int>(0);
final balance = Rx<Double>(0.0);
final number = Rx<Num>(0)
final items = Rx<List<String>>([]);
final myMap = Rx<Map<String, int>>({});
// 自定义类 - 可以是任何类
final user = Rx<User>();
第三种 更实用、更简单、更可取的方法,只需添加 .obs 作为value的属性。(推荐)
final name = ''.obs;
final isLogged = false.obs;
final count = 0.obs;
final balance = 0.0.obs;
final number = 0.obs;
final items = <String>[].obs;
final myMap = <String, int>{}.obs;
// 自定义类 - 可以是任何类
final user = User().obs;
监听自定义类数据的变化
第一步:应用程序入口设置
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(
title: "GetX",
home: MyHomePage(),
);
}
}
第二步:创建Person 类
import 'package:get/get.dart';
class Person {
// rx 变量
RxString name = "Jimi".obs;
RxInt age = 18.obs;
}
第三步:获取类属性值以及改变值
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import './person.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var person = Person();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Getx Obx"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Obx(() => Text(
"我的名字是 ${person.name.value}",
style: const TextStyle(color: Colors.red, fontSize: 30),
))
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
person.name.value = person.name.value.toUpperCase();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Flutter Getx 简单的状态管理(依赖管理)GetxController
Getx 依赖管理简介
Get有一个简单而强大的依赖管理器,它允许你只用1行代码就能检索到与你的Bloc或Controller相同的类,无需Provider context,无需inheritedWidget。
Controller controller = Get.put(Controller());
// 而不是 Controller controller = Controller();
想象一下,你已经浏览了无数条路由,现在你需要拿到一个被遗留在控制器中的数据,那你需要一个状态管理器与Provider或Get_it一起使用来拿到它,对吗?用Get则不然,Get会自动为你的控制器找到你想要的数据,而你甚至不需要任何额外的依赖关系。
Controller controller = Get.find();
//是的,它看起来像魔术,Get会找到你的控制器,并将其提供给你。你可以实例化100万个控制器,Get总会给你正确的控制器。
多页面之间的数据共享
- Flutter默认创建的 "计数器 "项目有100多行(含注释),为了展示Get的强大功能,我将使用 GetX 重写一个"计数器 Plus版",实现:
- 每次点击都能改变状态
- 在不同页面之间切换
- 在不同页面之间共享状态
- 将业务逻辑与界面分离
第一步:应用程序入口设置
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
....
);
}
}
第二步:新建CountController
import 'package:get/get.dart';
class CountController extends GetxController{
var count = 0.obs;
void inc(){
count++;
update();
}
void dec(){
count--;
update();
}
}
第三步:Home.dart执行inc方法
import 'package:flutter/material.dart';
import '../../controller/count.dart';
import 'package:get/get.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
CountController countController = Get.put(CountController());
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(()=>Text("${countController.count}",style:
Theme.of(context).textTheme.headline1)),
ElevatedButton(onPressed: (){
countController.inc();
}, child: const Text("数值+1"))
],
),
);
}
}
第四步:Category.dart执行dec方法
你可以让Get找到一个正在被其他页面使用的Controller,并将它返回给你。
final countController= Get.find<CountController>();
// 或者
final CountController countController = Get.find();
import 'package:flutter/material.dart';
import '../../controller/count.dart';
import 'package:get/get.dart';
class CategoryPage extends StatefulWidget {
const CategoryPage({super.key});
@override
State<CategoryPage> createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage> {
final CountController countController = Get.find();
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text("${countController.count}",
style: Theme.of(context).textTheme.headline1)),
ElevatedButton(
onPressed: () {
countController.dec();
},
child: const Text("数值-1"))
],
),
);
}
}
GetxController 绑定数据的几种方法
方法1:
CountController countController = Get.put(CountController());
// 或者
final CountController countController = Get.find();
Obx(()=>Text("${countController.count}",style:
Theme.of(context).textTheme.headline1)),
方法2:
只是绑定数据无需调用Get.put(CountController());
GetX<CountController>(
init: CountController(),
builder: (controller) {
return Text(
"${controller.count}",
style: const TextStyle(color: Colors.green, fontSize: 30),
);
},
),
方法3:
CountController countController = Get.put(CountController());
或者
final CountController countController = Get.find();
GetBuilder<CountController>(
init: countController,
builder: (controller) {
return Text(
"${controller.count}",
style: const TextStyle(color: Colors.green, fontSize: 30),
);
},
)