运营好还是网站开发好,wordpress视差插件,android studio模拟器,seo免费工具Flutter 状态管理之GetX 前言正文一、创建项目二、状态组件三、状态更新UI四、GetX库① 添加依赖② 局部刷新③ 全局刷新 五、源码 前言 Flutter使用的是声明式UI#xff0c;是通过状态去更新UI组件的#xff0c;因此我们首先就要学习状态的使用。同样为了简化原本的状态使用… Flutter 状态管理之GetX 前言正文一、创建项目二、状态组件三、状态更新UI四、GetX库① 添加依赖② 局部刷新③ 全局刷新 五、源码 前言 Flutter使用的是声明式UI是通过状态去更新UI组件的因此我们首先就要学习状态的使用。同样为了简化原本的状态使用我们会使用Getx库。
正文 之前说要写Flutter一拖就是一年多有些不好意思。现在都24年了终于等到你下面还是按照我们最属于的思路来吧。
一、创建项目
首先我们创建项目Flie → New → New Flutter Project... 然后选择Flutter这里可以看到Flutter SDK path已经配置好了点击Next。 然后输入工程名为study_state目前我们只考虑Android和iOS两个平台因此其他的就不勾选了。 点击Create按钮完成项目的创建。 创建后我们可以看到main.dart这里是flutter启动文件同时我启动了一个模拟器用的雷电模拟器至于为什么不用AS自带的模拟器只能说懂的都懂不懂的也劝你别去用。 下面我们首先运行在模拟器上看看运行到模拟器的时间会比较长不过运行之后当你再次修改代码之后可以通过热重载直接在模拟器上显示出修改后的内容快捷键是Ctrl S图标是一个黄色的闪电。有时候快捷键不生效则你可以手动的点击这个闪电按钮如果也不生效就重新安装总会生效的做开发就要有一颗平常心。
运行好了效果如下图所示 当我们点击右下角的浮动按钮之后就会看到屏幕中的数字加1关于这个里面的内容我在第一篇Flutter文章中就介绍过了因此下面我们就不过多介绍代码我们将main.dart中的代码全部清空如下图所示 然后我们再来一步一步的写代码在这个过程中我们能了解到更多的东西。
二、状态组件
首先我们写一个main函数代码如下所示
void main() {}然后我们在这个当前这个文件中再写一个MyApp类如下图所示 这里我继承了StatelessWidget这是一个无状态组件在你输入之后会有提示注意一下导包是material.dart中的推荐你使用这个里面的StatelessWidgetMyApp的代码如下所示
class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {// TODO: implement buildthrow UnimplementedError();}
}这里重新里面的build()函数在这里面我们就可以写UI了但是我们先不写你可以把MyApp理解为Android的Application然后我们再写一个HomePage继承StatefulWidget 这是一个有状态的组件重写里面的createState()代码我们也先不改你可以把HomePage 理解为Activity。
class HomePage extends StatefulWidget {overrideStateStatefulWidget createState() {// TODO: implement createStatethrow UnimplementedError();}
}然后我们再写一个_HomePageState 类继承自State这是一个抽象类支持有状态组件那么我们传递HomePage进去代码如下所示
class _HomePageState extends StateHomePage {overrideWidget build(BuildContext context) {// TODO: implement buildthrow UnimplementedError();}
}这里面的build()函数中我们同样可以设置UI现在我们就了解了无状态和有状态两种组件在 Flutter 中有两种类型的小部件StatelessWidget 和 StatefulWidget。它们在功能和使用上有一些区别。 StatelessWidget无状态小部件 它是一个不可变的小部件意味着一旦创建就不能再更改它的状态。它的属性props在创建时被设置并且在整个生命周期中保持不变。当父级小部件发生更改时StatelessWidget 将重新构建但状态不会发生变化。由于不需要跟踪状态的改变StatelessWidget 的构建过程更加高效。 StatefulWidget有状态小部件 它是一个可变的小部件可以在运行时改变其内部状态。它具有一个持久的状态对象State用于存储和跟踪小部件的变化。当父级小部件发生更改时StatefulWidget 通过更新关联的状态对象来重新构建。StatefulWidget 通常用于处理需要响应用户交互或动态变化的情况。
在实践中以下是一些使用场景的示例
使用 StatelessWidget当小部件的外观和内容不会随时间而改变时推荐使用 StatelessWidget例如静态文本、图标等。使用 StatefulWidget当小部件的外观和内容需要根据用户交互、数据变化或其他条件动态更新时需要使用 StatefulWidget例如表单、列表视图等。 需要注意的是StatefulWidget 与 State 对象一起工作后者存储和管理小部件的状态。当使用 StatefulWidget 时通常需要同时创建一个与之关联的状态类。 总结起来StatelessWidget 是一个不可变的小部件适用于静态内容而 StatefulWidget 是一个可变的小部件适用于需要跟踪状态变化的场景。
下面我们将前面所写的代码给串起来首先是main函数中修改后代码如下所示
void main() {return runApp(MyApp());
}这里使用了一个runApp()函数里面传入一个组件即可无论是什么组件这里我们传入MyApp()那么当我们启动之后会运行main函数然后渲染MyApp()组件下面我们修改MyApp的代码如下所示
class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {return MaterialApp(title: Study State,theme: ThemeData(useMaterial3: true),home: HomePage(),);}
}这里我们通过构建MaterialApp()在home属性中添加了HomePage()那么内容就以HomePage()为主了再看HomePage 代码如下所示
class HomePage extends StatefulWidget {const HomePage({super.key});overrideStateHomePage createState() {return _HomePageState();}
}这里面的key是一个标识HomePage组件的唯一键createState()方法在创建HomePage时会被调用。createState()方法返回一个_HomePageState对象它是HomePage的具体状态类。状态类(State)的主要作用是管理StatefulWidget的状态并根据需要更新小部件的UI。每当HomePage的状态发生变化时Flutter会调用_HomePageState类中的build方法来构建最新的UI下面我们再来看_HomePageState代码如下所示
class _HomePageState extends StateHomePage {overrideWidget 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(按钮))],),),),);}
}这里首先使用了一个Scaffold()这是一个页面的构成组件body属性定义了页面的主要内容区域。在body中使用Align组件将其子组件在父容器中居中显示。Alignment.center表示子组件在父容器中的居中对齐。 Align的子组件是一个Container设置宽度和高度200x200。alignment属性设置为Alignment.center将子组件在自身容器中进行居中对齐。child属性是一个Column组件这是一个纵向布局组件里面是一个数组可以包含多个组件它包含了两个子小部件一个Text组件和一个带有文本的ElevatedButton组件。在按钮的点击事件中我们打印一下日志下面我们重新运行一下。 点击按钮后看控制台。 三、状态更新UI 下面我们通过状态来更新UI比如我们将点击按钮将文本内容改成大写再点击改成小写下面我们修改_HomePageState类中的代码如下所示
class _HomePageState extends StateHomePage {String test study state;bool isUppercase false;void changeText() {setState(() {isUppercase !isUppercase;print(isUppercase ? 大写 : 小写);});}overrideWidget 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(按钮))],),),),);}
}首先我们定义了两个变量内容和是否大小写然后写了一个changeText()函数这个函数中使用了setState(() {})用于改变状态在这里面修改了isUppercase 的值然后Text(isUppercase ? test.toUpperCase() : test.toLowerCase())这行代码在初始情况下显示为小写然后我们点击按钮调用changeText()函数函数中更改isUppercase 的值通过setState就会刷新UI此时isUppercase 为true则Text中显示大写再点击一下为false就变成小写。这就是状态改变驱动UI。
主要改动地方如下图所示 控制台日志如下图所示 通过这种方式当我们有数据改变时就可以更新UI了只不过刚开始你需要习惯这种方式。声明式UI基本上都是这种方式了解了Flutter基本的状态更新UI下面我们再来学习一下GetX这个库。
四、GetX库 GetX是一个基于Flutter的状态管理和路由导航的解决方案提供了简单、强大、高性能的工具和功能以简化Flutter应用程序的开发过程。地址是GetX可以去了解一下下面我们来使用它。
① 添加依赖
在项目的pubspec.yaml文件中将GetX添加为依赖项
dependencies:get:添加位置如下图所示 这里后面我并没有写版本号这表示获取最新的版本如需获取指定版本写法如下所示
dependencies:get: ^4.3.8然后点击Pub get获取并安装GetX库如下图所示 你也可以在Terminal命令行中输入flutter pub get命令获取并安装GetX库。安装成功后你可以在控制台看到如下图所示 GetX安装成功同时我们知道最新的版本是4.6.6。
② 局部刷新 在使用之前我们先将原有的代码分离一下也就是将Application和Activity分开在lib下创建一个home文件夹文件夹下新建一个home_page.dart文件然后我们将main.dart中的部分代码挪到这里面代码如下所示
import package:flutter/material.dart;class HomePage extends StatefulWidget {const HomePage({super.key});overrideStateHomePage createState() {return _HomePageState();}
}class _HomePageState extends StateHomePage {String test study state;bool isUppercase false;void changeText() {setState(() {isUppercase !isUppercase;print(isUppercase ? 大写 : 小写);});}overrideWidget 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(按钮))],),),),);}
}然后我们再看main.dart中的代码
import package:flutter/material.dart;import home/home_page.dart;void main() {return runApp(MyApp());
}class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {return MaterialApp(title: Study State,theme: ThemeData(useMaterial3: true),home: HomePage(),);}
}现在我们就进行了分离下面就可以在home_page.dart中进行GetX的使用了注意在使用的时候需要导包在哪里用就在哪里导包然后编辑器也会提示你导包的。
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 ? 大写 : 小写);}overrideWidget 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所继承的组件由StatefulWidget改成了StatelessWidget然后为变量添加了.obs后缀使这个变量可观察。然后在changeText()方法中修改可观察变量的值。最后使用Obx包裹需要局部刷新的组件例如Obx(() Text(test.value))当可观察变量值更新时Obx包裹中的内容就会进行刷新。 现在这种模式我们还可以再改一下将涉及到数据改变的部分剥离出去让我们的页面只专注于显示和更新即可在home目录下新建一个home_controller.dart文件里面的代码如下
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注意导包别导错了然后将changeText()方法挪过来即可下面我们再会到home_page.dart中修改代码如下所示
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});overrideWidget 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(按钮))],),),),);}
}在build()方法中通过Get.put(HomeController())得到控制器对象然后在Text中通过控制器得到里面的值同样可以调用里面的方法这样我们就将业务和UI分离了。你现在运行之后效果是和之前一样的可以试试呢。
③ 全局刷新 全局刷新我们需要使用到GetBuilder实际上他就是setState的优化下面我们改动一下home_controller中的代码如下所示
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();}
}这里就将.obs后缀去掉了就不是一个可观察变量了同时我增加了一个参数用于显示按钮的文字在changeText()方法中进行修改最后调用update()进行全局更新注意update()方法是结合GetBuilder使用的下面我们改写home_page中的代码如下所示
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});overrideWidget build(BuildContext context) {return Scaffold(body: GetBuilderHomeController(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包裹构建一个可以全局刷新的组件在初始化时得到HomeController()然后在builder中就可以返回一个组件组件中直接使用controller对象进行参数和方法的使用。
效果图如下所示 五、源码
源码地址study_state