一.Getx状态管理
调用defaultDialog 调用snacker 调用BottomSheet以及改变主题
1、状态管理、Flutter Getx介绍
1.1、状态管理
通俗的讲:当我们想在多个页面(组件/Widget)之间共享状态(数据),或者一个页面(组
件/Widget)中的多个子组件之间共享状态(数据),这个时候我们就可以用Flutter中的状态管理来管理统一的状态(数据),实现不同组件之间的传值和数据共享。
现在Flutter的状态管理方案很多,redux、bloc、state、provider、Getx.
provider是官方提供的状态管理解决方案,主要功能就是状态管理。Getx是第三方的状态管理插件,不仅具有状态管理的功能,还具有路由管理、主题管理、国际化多语言管理、Obx局部更新、网络请求、数据验证等功能,相比其他状态管理插件Getx简单、功能强大并且高性能。
1.2、Flutter Getx介绍
GetX是Flutter上的一个轻量且强大的解决方案,Getx为我们提供了高性能的状态管理、智能的依赖注入和便捷的路由管理。
·Getx 有3个基本原则:
。性能:GetX专注于性能和最小资源消耗。GetX打包后的apk占用大小和运行时的内存占用
与其他状态管理插件不相上下。
效率:GetX的语法非常简捷,并保持了极高的性能,能极大缩短你的开发时长。
。结构:GetX可以将界面、逻辑、依赖和路由完全解耦,用起来更清爽,逻辑更清晰,代码
更容易维护
GetX 并不臃肿,却很轻量。如果你只使用状态管理,只有状态管理模块会被编译,其他没用到的东西都不会被编译到你的代码中。它拥有众多的功能,但这些功能都在独立的容器中,只有在使用后才会启动。
1.3 代码示例
第一步先安装第二步该getmertialApp
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _alertDialog(context) async {
var result = await showDialog(
barrierDismissible: false, //表示点击灰色背景时是否消失弹出框
context: context,
builder: (context) {
return AlertDialog(
title: const Text("提示信息!"),
content: const Text("您确定要删除吗"),
actions: [
TextButton(
onPressed: () {
print("ok");
Navigator.of(context).pop("ok"); //点击按钮让AlterDialog消失
},
child: const Text("确定")),
TextButton(
onPressed: () {
print("cancle");
Navigator.of(context).pop("取消"); //点击按钮让AlterDialog消失
},
child: const Text("取消")),
],
);
});
print("----------");
print(result);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Title'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
_alertDialog(context);
},
child: const Text("Flutter默认的dialog")),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Get.defaultDialog(
title: "提示信息!",
middleText: "您确定要删除吗?",
confirm: ElevatedButton(
onPressed: () {
print("确定");
//Navigator.of(context).pop();//点击确定就会消失
Get.back();
},
child: const Text("确定")),
cancel: ElevatedButton(
onPressed: () {
print("取消");
Get.back();
},
child: const Text("取消")),
);
},
child: const Text("Getx defaultDialog")),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
Get.snackbar("提示?", "您还没有登录",
snackPosition: SnackPosition.BOTTOM);
},
child: const Text("Getx snakbar")),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
Get.bottomSheet(Container(
// color: Colors.white,
color: Get.isDarkMode ? Colors.black26 : Colors.white,
height: 200,
child: Column(children: [
ListTile(
leading: Icon(
Icons.wb_sunny_outlined,
// color: Colors.black87,
color: Get.isDarkMode ? Colors.white : Colors.black87,
),
onTap: () {
//切换主题
Get.changeTheme(ThemeData.light());
Get.back();
},
title: Text(
"白天模式",
style: TextStyle(
// color: Colors.black87,
color: Get.isDarkMode ? Colors.white : Colors.black87,
),
),
),
ListTile(
leading: Icon(
Icons.wb_sunny,
// color: Colors.black87,
color: Get.isDarkMode ? Colors.white : Colors.black87,
),
onTap: () {
Get.changeTheme(ThemeData.dark());
Get.back();
},
title: Text(
"夜晚模式",
style: TextStyle(
// color: Colors.black87,
color: Get.isDarkMode ? Colors.white : Colors.black87,
),
),
),
]),
));
},
child: const Text("Getx bottomSheet切换主题")),
],
)),
);
}
}
1.4 结果
二. Getx路由管理
2.1 常用代码
Getx路由管理在所用get文件里也要引入get
Getx.to()实现普通路由跳转
Get.toNamed("/login");实现命名路由跳转
Get.back();返回上一级页面
Get.oddAll();返回到根
Get配置路由以及动画
defaultTransition可以配置默认动画
GetPage可以配置动态路由
2.2 代码实例
在user.dart里实现路由跳转
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class UserPage extends StatefulWidget {
const UserPage({super.key});
@override
State<UserPage> createState() => _UserPageState();
}
class _UserPageState extends State<UserPage> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print("执行跳转");
//Navigator.pushNamed(context, "/login");
Get.toNamed("/login");
},
child: const Text("登录")),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: () {
// Navigator.pushNamed(context, "/registerFirst");
Get.toNamed("/registerFirst");
},
child: const Text("注册"))
],
),
);
}
}
返回上一层在login.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("登录页面"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("登录跳转演示,执行登录后返回上一个页面"),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: () {
//返回上一层
//Navigator.of(context).pop();
Get.back();
},
child: const Text("执行登录"))
],
),
));
}
}
返回跟页面在registerThird.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter05/tabs.dart';
class RegisterThirdPage extends StatefulWidget {
const RegisterThirdPage({super.key});
@override
State<RegisterThirdPage> createState() => _RegisterThirdPageState();
}
class _RegisterThirdPageState extends State<RegisterThirdPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("注册第三步")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("注册第三步"),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: () {
//Navigator.pushNamed(context, "/registerSecond");
//返回根页面
// Navigator.of(context).pushAndRemoveUntil(
// MaterialPageRoute(builder: (BuildContext context) {
// return const Tabs(
// index: 4, //返回用户页面,从0开始数
// );
// }), (route) => false);
Get.offAll(const Tabs(
index: 4,
));
},
child: const Text("完成注册"))
],
),
));
}
}
2.3 Get.off(NextScreen());
进入下一个页面,但是没有返回上一个页面的选项(用于闪屏页,登录页面等).
没有返回标志
user.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../user/registerFirst.dart';
class UserPage extends StatefulWidget {
const UserPage({super.key});
@override
State<UserPage> createState() => _UserPageState();
}
class _UserPageState extends State<UserPage> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print("执行跳转");
//Navigator.pushNamed(context, "/login");
Get.toNamed("/login");
},
child: const Text("登录")),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: () {
// Navigator.pushNamed(context, "/registerFirst");
// Get.toNamed("/registerFirst");
Get.off(const RegisterFirstPage()); //没有返回按钮
},
child: const Text("注册")),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: () {
// Navigator.pushNamed(context, "/registerFirst");
Get.toNamed("/shop", arguments: {"id": 3456});
//Get.off(const RegisterFirstPage());//没有返回按钮
},
child: const Text("跳转路由传值"))
],
),
);
}
}
三. Getx配置路由以及动画
3.1 示例代码
shop.dart中不需要接受任何值
import 'package:flutter/material.dart';
class ShopPage extends StatefulWidget {
//接受命名路由跳转传值
//final Map arguments;
// const ShopPage({super.key, required this.arguments});
const ShopPage({super.key, });
@override
State<ShopPage> createState() => _ShopPageState();
}
class _ShopPageState extends State<ShopPage> {
@override
void initState() {
//在高端页面获取上一个页面的传值
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
//页面
appBar: AppBar(
//导航
title: const Text("shop"),
),
body: const Center(
child: Text("shop页面"),
));
}
}
传值,设计路由,然后在对应页面获取值
main.dart 不需要routers.dart
import 'package:flutter/material.dart';
import 'package:flutter05/tabs.dart';
import 'package:get/get.dart';
import 'package:flutter05/shop.dart';
import 'package:flutter05/user/login.dart';
import 'package:flutter05/user/registerFirst.dart';
import 'package:flutter05/user/registerSecond.dart';
import 'package:flutter05/user/registerThird.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: "/", //如果想一打开就在哪个页面,就写入哪个页面:例如:"/login"
//onGenerateRoute: onGenerateRoute,
defaultTransition: Transition.rightToLeftWithFade, //配置动画效果
getPages: [
GetPage(name: "/", page: () => const Tabs()),
GetPage(name: "/shop", page: () => const ShopPage()),
GetPage(name: "/login", page: () => const LoginPage()),
GetPage(
name: "/registerFirst",
page: () => const RegisterFirstPage(),
transition: Transition.fade),
GetPage(
name: "/registerSecond", page: () => const RegisterSecondPage()),
GetPage(name: "/registerThird", page: () => const RegisterThirdPage()),
],
);
}
}
抽离路由
routers.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter05/tabs.dart';
import 'package:flutter05/shop.dart';
import 'package:flutter05/user/login.dart';
import 'package:flutter05/user/registerFirst.dart';
import 'package:flutter05/user/registerSecond.dart';
import 'package:flutter05/user/registerThird.dart';
class AppPage {
static final routes = [
GetPage(name: "/", page: () => const Tabs()),
GetPage(name: "/shop", page: () => const ShopPage()),
GetPage(name: "/login", page: () => const LoginPage()),
GetPage(
name: "/registerFirst",
page: () => const RegisterFirstPage(),
transition: Transition.fade),
GetPage(name: "/registerSecond", page: () => const RegisterSecondPage()),
GetPage(name: "/registerThird", page: () => const RegisterThirdPage()),
];
}
main.dart
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: "/", //如果想一打开就在哪个页面,就写入哪个页面:例如:"/login"
//onGenerateRoute: onGenerateRoute,
defaultTransition: Transition.rightToLeftWithFade, //配置动画效果
// getPages: [
// GetPage(name: "/", page: () => const Tabs()),
// GetPage(name: "/shop", page: () => const ShopPage()),
// GetPage(name: "/login", page: () => const LoginPage()),
// GetPage(
// name: "/registerFirst",
// page: () => const RegisterFirstPage(),
// transition: Transition.fade),
// GetPage(
// name: "/registerSecond", page: () => const RegisterSecondPage()),
// GetPage(name: "/registerThird", page: () => const RegisterThirdPage()),
// ],
getPages: AppPage.routes,
);
}
}
四. 中间件
4.1 示例代码
新建一个shopMiddleware.dart
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
class ShopMiddleWare extends GetMiddleware {
RouteSettings? redirect(String? route) {
print(route);
return null;//跳转到以前的路由
}
}
然后再routers.dart中引入shopMiddleware.dart,在对应页面的路由上引入
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter05/tabs.dart';
import 'package:flutter05/shop.dart';
import 'package:flutter05/user/login.dart';
import 'package:flutter05/user/registerFirst.dart';
import 'package:flutter05/user/registerSecond.dart';
import 'package:flutter05/user/registerThird.dart';
import '../Middleware/shopMiddleware.dart';
class AppPage {
static final routes = [
GetPage(name: "/", page: () => const Tabs()),
GetPage(name: "/shop", page: () => const ShopPage(),middlewares: [
ShopMiddleWare()
]),
GetPage(name: "/login", page: () => const LoginPage()),
GetPage(
name: "/registerFirst",
page: () => const RegisterFirstPage(),
transition: Transition.fade),
GetPage(name: "/registerSecond", page: () => const RegisterSecondPage()),
GetPage(name: "/registerThird", page: () => const RegisterThirdPage()),
];
}
shopMiddleware.dart
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
class ShopMiddleWare extends GetMiddleware {
@override
RouteSettings? redirect(String? route) {
print("-----");
print(route);
//return null; //不做任何操作
//没有权限跳转到登录页面
return const RouteSettings(name: "/login", arguments: {});
}
}