Flutter 状态管理之GetX
- 前言
- 正文
-
- 一、创建项目
- 二、状态组件
- 三、状态更新UI
- 四、GetX库
-
- ① 添加依赖
- ② 局部刷新
- ③ 全局刷新
- 五、源码
前言
??Flutter使用的是声明式UI,是通过状态去更新UI组件的,因此我们首先就要学习状态的使用。同样为了简化原本的状态使用,我们会使用Getx库。
正文
??之前说要写Flutter,一拖就是一年多,有些不好意思。现在都24年了,终于等到你,下面还是按照我们最属于的思路来吧。
一、创建项目
首先我们创建项目,
然后选择Flutter,这里可以看到Flutter SDK path,已经配置好了,点击Next。
然后输入工程名为
点击Create按钮,完成项目的创建。
??创建后我们可以看到
??下面我们首先运行在模拟器上看看,运行到模拟器的时间会比较长,不过运行之后当你再次修改代码之后可以通过热重载直接在模拟器上显示出修改后的内容,快捷键是Ctrl + S,图标是一个黄色的闪电。有时候快捷键不生效则你可以手动的点击这个闪电按钮,如果也不生效就重新安装,总会生效的,做开发就要有一颗平常心。
运行好了,效果如下图所示:
??当我们点击右下角的浮动按钮之后就会看到屏幕中的数字加1,关于这个里面的内容我在第一篇Flutter文章中就介绍过了,因此下面我们就不过多介绍代码,我们将main.dart中的代码全部清空,如下图所示:
然后我们再来一步一步的写代码,在这个过程中我们能了解到更多的东西。
二、状态组件
首先我们写一个main函数,代码如下所示:
void main() { }
然后我们在这个当前这个文件中再写一个MyApp类,如下图所示:
??这里我继承了
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build throw UnimplementedError(); } }
??这里重新里面的build()函数,在这里面我们就可以写UI了,但是我们先不写,你可以把MyApp理解为Android的Application,然后我们再写一个HomePage,继承
class HomePage extends StatefulWidget { @override State<StatefulWidget> createState() { // TODO: implement createState throw UnimplementedError(); } }
??然后我们再写一个
class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { // TODO: implement build throw UnimplementedError(); } }
??这里面的
-
StatelessWidget (无状态小部件):- 它是一个不可变的小部件,意味着一旦创建就不能再更改它的状态。
- 它的属性(
props )在创建时被设置,并且在整个生命周期中保持不变。 - 当父级小部件发生更改时,
StatelessWidget 将重新构建,但状态不会发生变化。 - 由于不需要跟踪状态的改变,
StatelessWidget 的构建过程更加高效。
-
StatefulWidget (有状态小部件):- 它是一个可变的小部件,可以在运行时改变其内部状态。
- 它具有一个持久的状态对象(
State ),用于存储和跟踪小部件的变化。 - 当父级小部件发生更改时,
StatefulWidget 通过更新关联的状态对象来重新构建。 StatefulWidget 通常用于处理需要响应用户交互或动态变化的情况。
在实践中,以下是一些使用场景的示例:
- 使用
StatelessWidget :当小部件的外观和内容不会随时间而改变时,推荐使用StatelessWidget ,例如静态文本、图标等。 - 使用
StatefulWidget :当小部件的外观和内容需要根据用户交互、数据变化或其他条件动态更新时,需要使用StatefulWidget ,例如表单、列表视图等。
??需要注意的是,
??总结起来,
下面我们将前面所写的代码给串起来,首先是main函数中,修改后代码如下所示:
void main() { return runApp(MyApp()); }
??这里使用了一个
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "Study State", theme: ThemeData(useMaterial3: true), home: HomePage(), ); } }
??这里我们通过构建
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() { return _HomePageState(); } }
??这里面的key是一个标识HomePage组件的唯一键,
class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return Scaffold( body: Align( alignment: Alignment.center, child: Container( width: 200, height: 200, alignment: Alignment.center, child: Column( children: [ Text("Study State"), ElevatedButton(onPressed: () { print("点击了"); }, child: Text("按钮")) ], ), ), ), ); } }
??这里首先使用了一
??
点击按钮后,看控制台。
三、状态更新UI
??下面我们通过状态来更新UI,比如我们将点击按钮将文本内容改成大写,再点击改成小写,下面我们修改
class _HomePageState extends State<HomePage> { String test = "study state"; bool isUppercase = false; void changeText() { setState(() { isUppercase = !isUppercase; print(isUppercase ? "大写" : "小写"); }); } @override Widget build(BuildContext context) { return Scaffold( body: Align( alignment: Alignment.center, child: Container( width: 200, height: 200, alignment: Alignment.center, child: Column( children: [ Text(isUppercase ? test.toUpperCase() : test.toLowerCase()), ElevatedButton(onPressed: () { changeText(); }, child: const Text("按钮")) ], ), ), ), ); } }
??首先我们定义了两个变量,内容和是否大小写,然后写了一个
主要改动地方如下图所示:
控制台日志如下图所示:
??通过这种方式当我们有数据改变时就可以更新UI了,只不过刚开始你需要习惯这种方式。声明式UI基本上都是这种方式,了解了Flutter基本的状态更新UI,下面我们再来学习一下
四、GetX库
??
① 添加依赖
在项目的
dependencies: get:
添加位置如下图所示:
这里后面我并没有写版本号,这表示获取最新的版本,如需获取指定版本,写法如下所示:
dependencies: get: ^4.3.8
然后点击
??你也可以在
GetX安装成功,同时我们知道最新的版本是4.6.6。
② 局部刷新
??在使用之前我们先将原有的代码分离一下,也就是将Application和Activity分开,在lib下创建一个home文件夹,文件夹下新建一个
import 'package:flutter/material.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() { return _HomePageState(); } } class _HomePageState extends State<HomePage> { String test = "study state"; bool isUppercase = false; void changeText() { setState(() { isUppercase = !isUppercase; print(isUppercase ? "大写" : "小写"); }); } @override Widget build(BuildContext context) { return Scaffold( body: Align( alignment: Alignment.center, child: Container( width: 200, height: 200, alignment: Alignment.center, child: Column( children: [ Text(isUppercase ? test.toUpperCase() : test.toLowerCase()), ElevatedButton(onPressed: () { changeText(); }, child: const Text("按钮")) ], ), ), ), ); } }
然后我们再看
import 'package:flutter/material.dart'; import 'home/home_page.dart'; void main() { return runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "Study State", theme: ThemeData(useMaterial3: true), home: HomePage(), ); } }
??现在我们就进行了分离,下面就可以在
import 'package:get/get.dart';
修改代码如下所示:
import 'package:flutter/material.dart'; import 'package:get/get.dart'; class HomePage extends StatelessWidget { HomePage({super.key}); RxString test = "study state".obs; RxBool isUppercase = false.obs; void changeText() { isUppercase.value = !isUppercase.value; if (isUppercase.value) { test.value = test.value.toUpperCase(); } else { test.value = test.value.toLowerCase(); } print(isUppercase.value ? "大写" : "小写"); } @override Widget build(BuildContext context) { return Scaffold( body: Align( alignment: Alignment.center, child: Container( width: 200, height: 200, alignment: Alignment.center, child: Column( children: [ Obx(() => Text(test.value)), ElevatedButton(onPressed: () { changeText(); }, child: const Text("按钮")) ], ), ), ), ); } }
??这里我们说明一下,在首先使用GetX之后,我将HomePage所继承的组件由
??现在这种模式我们还可以再改一下,将涉及到数据改变的部分剥离出去,让我们的页面只专注于显示和更新即可,在home目录下新建一个
import 'package:get/get.dart'; ///Home页面控制器 class HomeController extends GetxController { RxString test = "study state".obs; RxBool isUppercase = false.obs; void changeText() { isUppercase.value = !isUppercase.value; if (isUppercase.value) { test.value = test.value.toUpperCase(); } else { test.value = test.value.toLowerCase(); } print(isUppercase.value ? "大写" : "小写"); } }
??这里就是创建一个HomeController类,继承自GetX的GetxController,注意导包别导错了,然后将
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:study_state/home/home_controller.dart'; class HomePage extends StatelessWidget { HomePage({super.key}); @override Widget build(BuildContext context) { final HomeController homeController = Get.put(HomeController()); return Scaffold( body: Align( alignment: Alignment.center, child: Container( width: 200, height: 200, alignment: Alignment.center, child: Column( children: [ Obx(() => Text(homeController.test.value)), ElevatedButton(onPressed: () { homeController.changeText(); }, child: const Text("按钮")) ], ), ), ), ); } }
??在
③ 全局刷新
??全局刷新我们需要使用到
import 'package:get/get.dart'; ///Home页面控制器 class HomeController extends GetxController { String test = "study state"; bool isUppercase = false; String btnText = "大写"; void changeText() { isUppercase = !isUppercase; if (isUppercase) { test = test.toUpperCase(); btnText = "小写"; } else { test = test.toLowerCase(); btnText = "大写"; } update(); } }
??这里就将
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:study_state/home/home_controller.dart'; class HomePage extends StatelessWidget { HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: GetBuilder<HomeController>( init: HomeController(), builder: (controller) { return Align( alignment: Alignment.center, child: Container( width: 200, height: 200, alignment: Alignment.center, child: Column( children: [ Text(controller.test), ElevatedButton( onPressed: controller.changeText, child: Text(controller.btnText)) ], ), ), ); }), ); } }
??使用GetBuilder包裹构建一个可以全局刷新的组件,在初始化时得到
效果图如下所示:
五、源码
源码地址:study_state