Flutter-Getx的使用
依赖
dependencies: get:
导入
import 'package:get/get.dart';
1.全局配置
MaterialApp --》 GetMaterialApp
GetMaterialApp不是使用Get的必要项
如果你只是使用 Get 进行状态管理或依赖管理,则不需要使用 GetMaterialApp。
GetMaterialApp 对于路由、通知栏、国际化、底部弹出窗口、对话框以及与路由和缺少上下文相关的高层 API 是必需的
2.简化代码
任何可观测对象都使用.obs修饰
class Controller { var count = 0.obs; }
让所有子界面共用数据
final Controller c = Get.put(Controller());
final Controller c = Get.find();
需要使用obx装饰部件
Obx(() => Text("Clicks: ${c.count}"))
3.状态管理 https://github.com/jonataslaw/getx/blob/master/documentation/en_US/state_management.md
声明可观察的变量-3种方式
final name = RxString(''); final isLogged = RxBool(false); final count = RxInt(0); final balance = RxDouble(0.0); final items = RxList<String>([]); final myMap = RxMap<String, int>({});
final name = Rx<String>(''); final isLogged = Rx<Bool>(false); final count = Rx<Int>(0); final balance = Rx<Double>(0.0); final number = Rx<Num>(0); final items = Rx<List<String>>([]); final myMap = Rx<Map<String, int>>({}); final user = Rx<User>();
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;
使用View监听值
GetX<Controller>( builder: (controller) { print("count 1 rebuild"); return Text('${controller.count1.value}'); }, )
把值变成状态管理值的两种方式
class RxUser { final name = "Camila".obs; final age = 18.obs; }
class User { User({String name, int age}); var name; var age; } final user = User(name: "Camila", age: 18).obs;
自定义类值的更新
class User() { User({this.name = '', this.age = 0}); String name; int age; } final user = User().obs;
//更新方式一 user.update( (user) { // this parameter is the class itself that you want to update user.name = 'Jonny'; user.age = 18; });
//更新方式二
user(User(name: 'João', age: 35));
//使用方式一
Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
//使用方式二
user().name;
监听值更改的回调
/// 每次更改都回调
ever(count1, (_) => print("$_ has been changed")); /// 监听一次 once(count1, (_) => print("$_ was changed once")); /// 防抖,键入结束时触发 debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1)); /// 忽略所有更改 interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
简单的状态管理使用
class Controller extends GetxController { int counter = 0; void increment() { counter++; update(); } } GetBuilder<Controller>( init: Controller(), builder: (_) => Text( '${_.counter}', ), )
在其他地方使用同一个Controller
class Controller extends GetxController {
static Controller get to => Get.find();
}
GetBuilder包含了StatefulWidgets的所有方法
GetBuilder<Controller>( initState: (_) => Controller.to.fetchApi(), dispose: (_) => Controller.to.closeStreams(), builder: (s) => Text('${s.username}'), ),
通过指定id表明只更新某个部件
update(['text']);
状态管理部件总结
GetBuilder vs GetX vs Obx vs MixinBuilder
4.路由管理 https://github.com/jonataslaw/getx/blob/master/documentation/en_US/route_management.md
Get.to(NextScreen()); Get.toNamed('/details'); Get.back(); Get.off(NextScreen()); //关闭当前页面并进入指定界面 Get.offAll(NextScreen());
配置
void main() { runApp( GetMaterialApp( initialRoute: '/', getPages: [ GetPage(name: '/', page: () => MyHomePage()), GetPage(name: '/second', page: () => Second()), GetPage( name: '/third', page: () => Third(), transition: Transition.zoom ), ], ) ); }
发送参数
Get.toNamed("/NextScreen", arguments: 'Get is the best');
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
接受参数
print(Get.parameters['id']); // out: 354 print(Get.parameters['name']); // out: Enzo
print(Get.arguments);
路由监听
GetMaterialApp( routingCallback: (routing) { if(routing.current == '/second'){ openAds(); } } )
小部件
Get.snackbar('Hi', 'i am a modern snackbar');
Get.rawSnackbar();
Get.dialog(YourDialogWidget());
await Get.defaultDialog( //使用await等待返回结果
onConfirm: () => print("Ok"),
middleText: "Dialog made in 3 lines of code"
);
Get.generalDialog(pageBuilder: (_,__,___){
return Text('data');
});
Get.bottomSheet();
5.依赖管理 https://github.com/jonataslaw/getx/blob/master/documentation/en_US/dependency_management.md
final Controller c = Get.put(Controller());
final Controller c = Get.find();
实例化Controller
Get.put<S>( // 必备:你想得到保存的类,比如控制器或其他东西。 // 注:"S "意味着它可以是任何类型的类。 S dependency // 可选:当你想要多个相同类型的类时,可以用这个方法。 // 因为你通常使用Get.find<Controller>()来获取一个类。 // 你需要使用标签来告诉你需要哪个实例。 // 必须是唯一的字符串 String tag, // 可选:默认情况下,get会在实例不再使用后进行销毁 // (例如:一个已经销毁的视图的Controller) // 但你可能需要这个实例在整个应用生命周期中保留在那里,就像一个sharedPreferences的实例或其他东西。 //所以你设置这个选项 // 默认值为false bool permanent = false, // 可选:允许你在测试中使用一个抽象类后,用另一个抽象类代替它,然后再进行测试。 // 默认为false bool overrideAbstract = false, // 可选:允许你使用函数而不是依赖(dependency)本身来创建依赖。 // 这个不常用 InstanceBuilderCallback<S> builder, )
按需实例化Controller
Get.lazyPut<S>( // 强制性:当你的类第一次被调用时,将被执行的方法。 InstanceBuilderCallback builder, // 可选:和Get.put()一样,当你想让同一个类有多个不同的实例时,就会用到它。 // 必须是唯一的 String tag, // 可选:类似于 "永久", // 不同的是,当不使用时,实例会被丢弃,但当再次需要使用时,Get会重新创建实例, // 就像 bindings api 中的 "SmartManagement.keepFactory "一样。 // 默认值为false bool fenix = false )
Get.putAsync<S>( // 必备:一个将被执行的异步方法,用于实例化你的类。 AsyncInstanceBuilderCallback<S> builder, // 可选:和Get.put()一样,当你想让同一个类有多个不同的实例时,就会用到它。 // 必须是唯一的 String tag, // 可选:与Get.put()相同,当你需要在整个应用程序中保持该实例的生命时使用。 // 默认值为false bool permanent = false )
使用create方法
Get.create<S>( // 需要:一个返回每次调用"Get.find() "都会被新建的类的函数。 // 示例: Get.create<YourClass>(()=>YourClass()) FcBuilderFunc<S> builder, // 可选:就像Get.put()一样,但当你需要多个同类的实例时,会用到它。 // 当你有一个列表,每个项目都需要自己的控制器时,这很有用。 // 需要是一个唯一的字符串。只要把标签改成名字 String name, // 可选:就像 Get.put() 一样, // 它是为了当你需要在整个应用中保活实例的时候 // 区别在于 Get.create 的 permanent默认为true bool permanent = true
使用Controller
final controller = Get.find<Controller>(); // 或者 Controller controller = Get.find();
移除Controller
Get.delete<Controller>(); //通常你不需要这样做,因为GetX已经删除了未使用的控制器。
使用Bindings进行View和Controller的结合
class HomeBinding implements Bindings { @override void dependencies() { Get.lazyPut<HomeController>(() => HomeController()); Get.put<Service>(()=> Api()); } }
getPages: [ GetPage( name: '/', page: () => HomeView(), binding: HomeBinding(), ), GetPage( name: '/details', page: () => DetailsView(), binding: DetailsBinding(), ), ];
getPages: [
GetPage(
name: '/',
page: () => HomeView(),
binding: BindingsBuilder(() {
Get.lazyPut<ControllerX>(() => ControllerX());
Get.put<Service>(()=> Api());
}),
),
GetPage(
name: '/details',
page: () => DetailsView(),
binding: BindingsBuilder(() {
Get.lazyPut<DetailsController>(() => DetailsController());
}),
),
];
Get.to(Home(), binding: HomeBinding());
Get.to(DetailsView(), binding: DetailsBinding())
6.国际化
定义
import 'package:get/get.dart'; class Messages extends Translations { @override Map<String, Map<String, String>> get keys => { 'en_US': { 'hello': 'Hello World', }, 'de_DE': { 'hello': 'Hallo Welt', } }; }
使用
Text('title'.tr);
带参数
import 'package:get/get.dart'; Map<String, Map<String, String>> get keys => { 'en_US': { 'logged_in': 'logged in as @name with email @email', }, 'es_ES': { 'logged_in': 'iniciado sesión como @name con e-mail @email', } }; Text('logged_in'.trParams({ 'name': 'Jhon', 'email': 'jhon@example.com' }));
需要配置
return GetMaterialApp( translations: Messages(), locale: Locale('en', 'US'), fallbackLocale: Locale('en', 'UK'),//默认的语言 );
动态更改语言
Get.deviceLocale;//获取系统语言
var locale = Locale('en', 'US'); Get.updateLocale(locale);
7.更改主题
Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());
//个人建议
//如果只是更新暗夜模式使用dartMode
Get.changeThemeMode(Get.isDarkMode ? ThemeMode.light : ThemeMode.dark);
//注意这种方式必须在GetMaterialApp中添加theme和dartTheme
GetMaterialApp(home: MyPage(), theme: ThemeData.light(), darkTheme: ThemeData.dark(),)
8.网络请求
class HomeProvider extends GetConnect { @override void onInit() { // All request will pass to jsonEncode so CasesModel.fromJson() httpClient.defaultDecoder = CasesModel.fromJson; httpClient.baseUrl = 'https://api.covid19api.com'; // baseUrl = 'https://api.covid19api.com'; // It define baseUrl to // Http and websockets if used with no [httpClient] instance // It's will attach 'apikey' property on header from all requests httpClient.addRequestModifier((request) { request.headers['apikey'] = '12345678'; return request; }); // Even if the server sends data from the country "Brazil", // it will never be displayed to users, because you remove // that data from the response, even before the response is delivered httpClient.addResponseModifier<CasesModel>((request, response) { CasesModel model = response.body; if (model.countries.contains('Brazil')) { model.countries.remove('Brazilll'); } }); httpClient.addAuthenticator((request) async { final response = await get("http://yourapi/token"); final token = response.body['token']; // Set the header request.headers['Authorization'] = "$token"; return request; }); //Autenticator will be called 3 times if HttpStatus is //HttpStatus.unauthorized httpClient.maxAuthRetries = 3; } @override Future<Response<CasesModel>> getCases(String path) => get(path); }
9.路由中间件
强大的路由拦截机制,允许你在页面导航前后执行自定义逻辑(如权限验证、日志记录、数据预加载等)
10.其他的便捷属性
Get.arguments //获取传递的参数
Get.previousRoute //上一个路由
Get.rawRoute //根路由
Get.routing //路由信息
Get.isSnackbarOpen
Get.isDialogOpen
Get.isBottomSheetOpen
Get.removeRoute() //移除某个路由
Get.until() //关闭页面直到条件为true
Get.offUntil() //关闭页面直到条件为true,并且打开一个新的路由
Get.offNamedUntil() //同上
//获取平台信息
GetPlatform.isAndroid
GetPlatform.isIOS
GetPlatform.isMacOS
GetPlatform.isWindows
GetPlatform.isLinux
GetPlatform.isFuchsia
GetPlatform.isMobile
GetPlatform.isDesktop
GetPlatform.isWeb
//宽高(不可变)
Get.height
Get.width
//上下文
Get.context
//弹窗上下文
Get.contextOverlay
//宽高(可变)
context.width context.height
//宽高的倍数
context.heightTransformer() context.widthTransformer()
//等同于MediaQuery所使用的api
context.mediaQuerySize()
context.mediaQueryPadding()
context.mediaQueryViewPadding()
context.mediaQueryViewInsets()
context.orientation()
context.isLandscape()
context.isPortrait()
context.devicePixelRatio()
context.textScaleFactor()
context.mediaQueryShortestSide() //最短边,用于判断是手机还是平板
context.showNavbar()
context.isPhone() //是否是手机
context.isSmallTablet()
context.isLargeTablet()
context.isTablet() //是否是平板
/// watch: if the shortestSide is smaller than 300
/// mobile: if the shortestSide is smaller than 600
/// tablet: if the shortestSide is smaller than 1200
/// desktop: if width is largest than 1200
context.responsiveValue<T>()
11.Get的全局属性更改
//需要放在第一个路由的前面
Get.config( enableLog = true, defaultPopGesture = true, defaultTransition = Transitions.cupertino )
12.状态管理部件
部件内部更新-简单值
ValueBuilder<bool>( initialValue: false, builder: (value, updateFn) => Switch( value: value, onChanged: updateFn, ), onUpdate: (value) => print("Value updated: $value"), onDispose: () => print("Widget unmounted"), ),
obs动态变换
ObxValue((data) => Switch( value: data.value, onChanged: data, ), false.obs, ),
13.更改和获取 .obs 的值
//字符串类型
final name = 'GetX'.obs;
name.value = 'Hey';
name('Hello');
name() ;
//数字类型
final count = 0.obs;
count + 1;
count > 2;
//布尔值
final flag = false.obs;
flag.toggle();
//集合类型,像普通集合类型一样用就好了
final abc = [0,1,2].obs;
abc.add(12);
abc[3];
//对象类型
class User {
String name, last;
int age;
User({this.name, this.last, this.age});
@override
String toString() => '$name $last, $age years old';
}
final user = User(name: 'John', last: 'Doe', age: 33).obs;
user.value.name = 'Roi';
user.refresh(); //必须调用才能实现界面刷新
user.update((value){ //或者调用这个
value.name='Roi';
});
14.StateMixin 适合更新整个数据对象,界面可自动包含加载中,加载成功,加载失败,空数据
class Controller extends GetController with StateMixin<User>{}
change(data, status: RxStatus.success());
class OtherClass extends GetView<Controller> { @override Widget build(BuildContext context) { return Scaffold( body: controller.obx( (state)=>Text(state.name), onLoading: CustomLoadingIndicator(), onEmpty: Text('No data found'), onError: (error)=>Text(error), ), ); }
15.GetView:要使用GetController需要结合GetView使用
class AwesomeController extends GetController { final String title = 'My Awesome View'; } class AwesomeView extends GetView<AwesomeController> { @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(20), child: Text(controller.title), ); } }
16.GetResponsiveView:可针对不同的设备类型构建不同的布局
class MyPage extends GetResponsiveView<Controller> { MyPage({super.key}); @override Widget desktop() { } @override Widget phone() { } @override Widget tablet() { } @override Widget watch() { } }
17.GetWidget配合Get.create()使用:适合需要独立控制器实例的临时页面或组件
GetWidget<FormController>( init: Get.create<FormController>(() => FormController()), autoRemove: true, onDispose: (controller) { controller.saveDraft(); // 销毁前自动保存草稿 }, builder: (controller) => /*...*/, )
18.跟应用生命周期相同的实例 GetxService
Future<void> main() async { await initServices(); runApp(SomeApp()); } void initServices() async { print('starting services ...'); await Get.putAsync(() => DbService().init()); await Get.putAsync(SettingsService()).init(); print('All services started...'); } class DbService extends GetxService { Future<DbService> init() async { print('$runtimeType delays 2 sec'); await 2.delay(); print('$runtimeType ready!'); return this; } } class SettingsService extends GetxService { void init() async { print('$runtimeType delays 1 sec'); await 1.delay(); print('$runtimeType ready!'); } }
销毁只能调用 Get.reset()

浙公网安备 33010602011771号