前言
最近要正式开始写一个flutter项目了,我在浏览flutter如何进行框架设计的时候突然看到了一篇关于如何管理flutter状态的文章。flutter中的状态管理并不是很好理解,但是你需要在页面之间传值或者改变组件中的某个值的时候就必须更改状态。当我在这篇文章中看到作者使用了Getx这个组件,使用起来非常简便,除了帮你管理状态以外还能管理路由、主题、多语言,于是就开始了学习Getx之路。
Getx githubhttps://github.com/jonataslaw/getx
使用
新建一个flutter空项目(默认就是一个计数器demo)。先把Getx添加到pubspec.yaml文件中
dependencies:
get:
然后在这个默认计数器demo的基础上我们来使用Getx的强大功能
第一步
void main() => runApp(GetMaterialApp(home: Home()));
-
注意:这并不能修改Flutter的MaterialApp,GetMaterialApp并不是修改后的MaterialApp,它只是一个预先配置的Widget,它的子组件是默认的MaterialApp。你可以手动配置,但绝对没有必要。GetMaterialApp会创建路由,注入它们,注入翻译,注入你需要的一切路由导航。如果你只用Get来进行状态管理或依赖管理,就没有必要使用GetMaterialApp。GetMaterialApp对于路由、snackbar、国际化、bottomSheet、对话框以及与路由相关的高级apis和没有上下文(context)的情况下是必要的。
-
注2: 只有当你要使用路由管理(
Get.to()
,Get.back()
等)时才需要这一步。如果你不打算使用它,那么就不需要做第1步
第二步
创建业务逻辑类,把所有的变量,方法,控制器都放在这个业务逻辑类中。这里多了一个我们看不懂的代码,“0.obs”,先不用管这句代码有什么用,我们先继续往下走。
class Controller extends GetxController{
var count = 0.obs;
increment() => count++;
}
第三步
创建主页Home和第二个页面Other,使用Get框架后就基本不用创建有状态的组件了,即StatefulWidget
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}")));
}
}
到此,我们就可以直接运行并打开这个app,可以看到我们实现了在StatelessWidget组件中实现了状态改变,这是怎么做到的呢??
使用原理
我们在Controller类中声明了一个变量count = 0.obs,由于dart的语法糖我们在这并不知道这个变量是什么类型的。我们可以在这个GetxController的生命周期里,把count变量的类型打印出来看看。
class Controller extends GetxController{
var count = 0.obs;
increment() => count++;
@override
void onInit() {
super.onInit();
print(count.runtimeType);
}
}
可以看到,打印出来的类型是RxInt,Int类型我们熟呀,但是前面加了个Rx这又是啥?
这其实是Getx框架中定义的一个类型叫做响应式变量,Rx_Type,后面跟的Type可以是任意基础类型,包括list,map 等,还能声明自定义响应式变量。
声明响应式变量官方给了三种办法,前面两种不怎么常用,最实用的是第三种方法。
第三种方法:
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;
只需要在变量的末尾添加一个.obs,就可以把这个变量变成可观察的。
使用时需要用Obx()把组件包裹起来,只要观察的值发生了变化,这个组件就会重建