flutter-状态管理4-get的使用
2021-04-02 本文已影响0人
浮华_du
一、首先,依然是计数器的
1.构建共享数据
-
update()
使用GetBuilder 获取共享数据,并操作变化时,需要执行update()才能被通知到GetBuilder. -
.obs
给数据源加了.obs意味着 将其变成了rx响应数据(此例子中即RxInt),可以直接使用Obx语法监听,并操作变化.无需调用update()方法
class CountController extends GetxController {
var _counter = 0.obs;
get counter => _counter;
void increment() {
_counter++;
update();
}
@override
void onInit() {
super.onInit();
print('CountController--onInit');
}
@override
void onReady() {
super.onReady();
print('CountController--onReady');
}
@override
void onClose() {
super.onClose();
print('CountController--onClose');
}
}
2.获取controller, 操作数据
使用GetBuilder获取controller
1.需要在使用前 或 init参数中初始化共享数据Controller
(1) 使用前初始化的方式:CountController initController = Get.put(CountController());
(2) GetBuilder 的init参数初始化方式:
GetBuilder<CountController>(
init: CountController(), //这里不初始化 , 就在上面初始化
tag: "init_tag", //这里init不初始化,也不要设置这个tag; 设置了tag 数据就不是共享的了
builder: ...
)
-
2.获取数据改变数据的方式:
(1)可以使用build内返回的controller来获取数据和改变数据;
(2)可以用初始化initController获取数据和改变数据
(3)可以用Get.find<CountController>()可以用来获取数据和改变数据
class GetTestPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('SimplePage--build');
CountController initController = Get.put(CountController()); //初始化
return GetBuilder<CountController>(
//GetBuilder不监听obs更改,更改必须通过调用controller.update()
// init: CountController(), //这里不初始化 , 就在上面初始化
// tag: "init_tag", //这里init不初始化,也不要设置这个tag; 设置了tag 数据就不是共享的了
builder: (controller) {
print("GetBuilder--refresh");
return Scaffold(
appBar: AppBar(title: Text('Get')),
body: Center(
child: Column(children: [
Text(
controller.counter.toString(),
style: TextStyle(fontSize: 30),
),
Text(
initController.counter.toString(),
style: TextStyle(fontSize: 30),
),
Text(
Get.find<CountController>().counter.toString(),
style: TextStyle(fontSize: 30),
),
FloatingActionButton(
heroTag: "get_test1_increment",
onPressed: () {
controller.increment();
// initController.increment();
// Get.find<CountController>().increment();
},
child: Icon(Icons.add),
),
])),
floatingActionButton: FloatingActionButton(
heroTag: "get_totest2",
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return GetTest2Page();
}));
},
child: Icon(Icons.next_plan),
),
);
});
}
}
使用GetX获取controller
- 使用及注意事项与GetBuilder相同(需要初始化controller;改变数据及获取数据的方式)
class GetTest2Page extends StatelessWidget {
const GetTest2Page({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
CountController initController = Get.put(CountController()); //Obx需要初始化
print('SimplePage2--build');
return Scaffold(
appBar: AppBar(title: Text('Get')),
body: Center(
child: Column(children: [
GetX<CountController>(
// init: CountController(),//默认在这里初始化,不初始化的话,将会使用上边初始化的Controller
builder: (controller) {
print('GetX--refresh');
return TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue)),
onPressed: () {
controller.increment();
},
child: Text(
'点击+1-----${controller.counter}',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.white),
),
);
},
),
Obx(() => TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue)),
onPressed: () {
initController.increment();
},
child: Text(
'点击+1-----${initController.counter}',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.white),
),
)),
Obx(() => Text(
'仅显示===${initController.counter}',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
)),
Obx(() => TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue)),
onPressed: () {
Get.find<CountController>().increment();
},
child: Text(
'点击+1-----${Get.find<CountController>().counter}',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.white),
),
)),
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue)),
onPressed: () {
Get.find<CountController>().increment();
},
child: Text(
'无法观察变化 +1 -----${Get.find<CountController>().counter}',
style:
TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
)
]),
),
);
}
}
使用Obx观察数据
- (1)数据源一定是Rx...(后面加.obs); 更新方法无需使用update()
- (2)使用前一定要初始化controller
- (3)Obx(() =>widget) widget内可以展示数据,改变数据
二、Get.find<CountController>()的内部实现
- (1)获取数据改变数据既然可以直接使用Get.find<CountController>()拿到controller,就能改变数据,展示数据,为什么还要使用上述的3种方法?
通过上面例子中的最后一个 "无法观察变化 +1"此按钮可以看出,直接使用Get.find<CountController>()拿到的controller,可以改变数据,但是这个按钮本身并不具备观察功能,改变数据时,这个值并不会刷新. - (2)通过源码可以看出,在初始化controller时,Get.put内部会先走_insert方法,然后走find方法,返回一个controller.
CountController initController = Get.put(CountController());
image.png
_insert方法 内部,会根据这个controller的tag或名字, 生成一个唯一key,并加入到_singl内.
image.png
find方法 会先从_initDependencies内部寻找是否有对应tag的controller可以返回(是否初始化,没有的话先初始化);有的话,直接返回,没有的话,通过key在_singl中拿到.
image.png
image.png
所以,当我们使用Get.find<CountController>()时,也是这样的调用流程,获取到的controller.这个controller与其他方式获取到的controller是同一个controller.
三、实际使用,渲染一个列表-- obx方式
- 1.共享数据
import 'package:get/get.dart';
class TestGetLogic extends GetxController {
RxList _list = [].obs;
get list => _list;
addListData(List data){
_list.addAll(data);
// update();
}
}
- 2.使用页面
class TestGetPage extends StatefulWidget {
@override
_TestGetPageState createState() => _TestGetPageState();
}
class _TestGetPageState extends State<TestGetPage> {
TestGetLogic logic;
_TestGetPageState() {
logic = Get.put(TestGetLogic());
}
@override
void initState() {
///模拟网络请求,拿到数据
Future.delayed(Duration(milliseconds: 360), () {
logic.addListData(["达拉崩吧", "崩德比迪")]);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Obx(() { //Obx配合.obs 数据刷新
return Text("${logic.list.length}");
}),
Obx(() {
return Expanded(
child: ListView.builder(
itemCount: logic.list.length,
itemBuilder: (context, index) {
return _listItem(logic.list[index]);
}),
);
}),
],
),
);
// body: GetBuilder<TestGetLogic>(
// builder: (controller) { //刷新需要配合update()
// return ListView.builder(
// itemCount: logic.list.length,
// itemBuilder: (context, index) {
// return _listItem("${logic.list[index]}");
// });
// }));
}
Widget _listItem(String str) {
return Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
padding: const EdgeInsets.all(5.0),
color: Colors.black12,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
str,
maxLines:1,
style: TextStyle(fontSize: 18,fontWeight: FontWeight.w500),
),
],
),
),
);
}
}
问题
本例仅实现了向list里面增加数据, 那如何清空数据,修改数据呢 ?(以下示例无法实现)
refreshListData(List data){
_list = data.obs;
}
removeAll(){
_list = [].obs;
}
欢迎点点小心心哦~