一、依赖注入
1.Get.put(普通)
• permanent:是否永久,默认 false 当实例不再使用时会进行销毁,true 则会一直保留。
• tag:标签,用于区分同一个类不同实例。
举例:以下为注入状态控制器。
步骤一:
创建UI页面
class MyOnePage extends StatelessWidget {
const MyOnePage({super.key});
@override
Widget build(context) {
return Scaffold(
.......
);
}
}
步骤二:
创建对应UI页面的业务逻辑类,该类继承GetController类,写入该页面所要维持的状态变量和方法
class MyOnePController extends GetxController{
// 变量 ...
// 方法 ...
}
步骤三:
用Get.put()注入该页面所对应的Controller类的实例化对象,让它可以在所有子路由都可用。其他页面可以通过Get.find()找到该对象,并使用它,如果该对象没有被销毁的话。
class MyOnePage extends StatelessWidget {
const MyOnePage({super.key});
@override
Widget build(context) {
final MyOnePageController c = Get.put(MyOnePageController ());
return Scaffold(
.......
);
}
}
2.Get.lazyPut(懒加载)
• fenix:类似’永久’,不同的是,当不使用时,实例会被丢弃,但当再次需要使用时,Get会重新创建实例
• tag:标签,用于区分同一个类不同实例。
举例:在状态管理需要find的时候,懒加载注入该页面所对应的Controller类的实例化对象。
步骤一:
同Get.put
步骤二:
同Get.put
步骤三:
final MyOnePageController c = Get.lazyPut(MyOnePageController ());
3.Get.putAsync(异步加载)
举例:Get.put()的异步版,以下为异步注入SharedPreferences实例。
Get.putAsync<SharedPreferences>(() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('counter', 10);
return prefs;
});
4.Get.create
• permanent:是否永久,默认 false 当实例不再使用时会进行销毁,true 则会一直保留。
• tag:标签,用于区分同一个类不同实例。
表示每次find的时候,都会创建一个新的实例对象。一般不常用。
Get.create(() => User());
User user = Get.find();
User user1 = Get.find();
print("Get.create 获取的对象比较 ${user == user1}"); // 结果为:false
二、状态管理
在Get(x)中,通常分为View层(UI层)、Logic层(业务逻辑+状态)。
1.简单状态
通过GetBuilder和手动update刷新,通常用于刷新ListView,GridView等包含大量List刷新状态的场景。
步骤一:
在Logic层,对业务逻辑需要进行update()刷新。
class CounterLogic extends GetxController {
var count = 0;
void increase() {
++count;
update();
}
}
步骤二:
在View层,用Getbuilder嵌套在需要刷新状态的Widget处。
class CounterPage extends StatelessWidget {
final CounterLogic logic = Get.put(CounterLogic()); // 依赖注入
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GetBuilder<CounterLogic>(builder: (logic) {
return Text(
'点击了 ${logic.count} 次'
);
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () => logic.increase(),
child: Icon(Icons.add),
),
);
}
}
2.响应式状态
通过Rx变量和Obx(()=>),每一个响应式变量,都会生成对应的GetStream,占用资源大,会对内存造成一定压力,但使用方便一点点。
步骤一:
在Logic层,将变量进行转换为响应式变量。
class CounterLogic extends GetxController {
var count = 0.obs; // 在值后面加上obs,即可转换为响应式变量
void increase() {
++count.value; // 对响应式变量进行计算时,需要加上.value
}
}
步骤二:
在View层,用Obx嵌套在需要刷新状态的Widget处。
class CounterPage extends StatelessWidget {
final CounterLogic logic = Get.put(CounterLogic()); // 依赖注入
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(() {
return Text(
'点击了 ${logic.count.value} 次'
);
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () => logic.increase(),
child: Icon(Icons.add),
),
);
}
}
三、路由管理
在MaterialApp前加上 “Get”,变成GetMaterialApp,从此不再有上下文(context)。
1.普通路由
方法一:进入下一个页面
Get.to(HelloPage(), arguments: {"msg":"hello"});
var map = Get.arguments; //获取参数
• page:进入的下一个页面Widget
• argument:传递参数
方法二:返回上一个页面
Get.back();
Get.back(result:'success'); // 返回数据
var data = await Get.to(NextPage()); // 获取返回数据
• result:返回数据参数
方法三:进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)
Get.off(NextScreen());
• page:进入的下一个页面Widget
方法四:进入下一个页面并取消之前的所有路由(在购物车、投票和测试中很有用)。
Get.offAll(NextScreen());
• page:进入的下一个页面Widget
2.命名路由(常用)
方法一:导航到下一个页面
Get.toNamed("/NextScreen");
Get.toNamed("/NextScreen/:user"); // 带这种参数,用parameters,而不是arguments
Get.parameters['user']
方法二:浏览并删除前一个页面
Get.offNamed("/NextScreen");
方法三:浏览并删除所有以前的页面
Get.offAllNamed("/NextScreen");
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo"); // 动态网页链接
Get.parameters['id'] // 获取动态网页链接参数,用parameters,而不是arguments
在使用命名路由时,先在GetMaterialApp定义路由。
void main() {
runApp(
GetMaterialApp(
initialRoute: '/', //初始化路由
getPages: [ //定义路由数组
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
],
unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()), // 未被定义的路由都会跳转到这里
)
);
}
3.Bindings(常用)
Bindings 主要是配合路由进行使用,当通过 GetX 路由进入页面时,会自动调用dependencies方法, 可以在这里进行依赖关系的注册等。
步骤一:依赖注册由原来的View层,放在现在的Binding中。
class CounterBinding implements Bindings {
@override void dependencies() {
Get.lazyPut<CounterController>(() => CounterController());
}
}
步骤二:在路由中,添加对应的Binding。
Get.to(CounterPage(), binding: CounterBinding()); // 普通路由
GetPage( name: '/count', page: () => CounterPage(), binding: CounterBinding() // 在GetMaterialApp-getPages配置)
四、组合技(实战技巧)
根据个人经验,在项目中,能简则简。
1.入口函数
void main() {
runApp(
GetMaterialApp(
getPages: Routes.routePage, // 代替原生的routes
title: 'xx',
initialRoute: '/one',
initialBinding: BindingsBuilder(
() => [Get.lazyPut<MyOneController>(() => MyOneController())])),
);
}
2.Routes
单独配置路由类,并在GetPage中直接Binding。
abstract class Routes {
static const String onePage = '/one';
static final routePage = [
GetPage(
name: onePage,
page: () => const OnePage(),
binding: BindingsBuilder(
() => [Get.lazyPut<OneController>(() => OneController())]))
];
}
3.GetView
对于单个控制器作为依赖项时,可以继承GetView类,帮我们实现了Get.find(),用的时候,直接使用controller即可。
class OnePage extends GetView<OneController> {
const OnePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('MyOnePage')),
body: Column(
children: [
GetBuilder<OneController>(
builder: (controller) => Text('${controller.obj}')),
TextButton(
onPressed: (() => controller.increment()),
child: const Text('+1'))
],
));
}
}
五、控件
1.SnackBars
类似于Toast,多用于各种消息提示。
Get.snackbar('Hi', 'i am a modern snackbar'),
2.BottomSheets
从底部弹出的面板。
Get.bottomSheet(
Container(
child: Wrap(
children: <Widget>[
ListTile(
leading: Icon(Icons.music_note),
title: Text('Music'),
onTap: () => {}),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video'),
onTap: () => {},
),
],
),
),
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30))),
)
3.Dialogs
Get.defaultDialog(middleText: "这是一个默认弹窗"),