前言
应用Bloc的时候,有一个让我至今为止非常在意的问题,无奈真正的跨页面交互!在重复的查阅官网文档后,应用一个全局Bloc的形式,实现了“伪”跨页面交互,具体可查看:flutter_bloc应用解析;fish_redux的播送机制是能够比拟完满的实现跨页面交互的,我也写了一篇近万字介绍如何应用该框架:fish_redux应用详解,对于中小型我的项目应用fish_redux,这会肯定水平上升高开发效率,最近尝试了GetX相干性能,解决了我的相当一部分痛点把整篇文章写完后,我马上把本人的一个demo外面所有Bloc代码全用GetX替换,且去掉了Fluro框架;感觉用Getx尽管会省掉大量的模板代码,但还是有些反复工作:创立文件夹,创立几个必备文件,写那些必须要写的初始化代码和类;稍微繁琐,为了对得起GetX给我开发带来的微小便当,我就花了一些工夫,给它写了一个插件! 下面这反复的代码,文件,文件夹通通能一键生成!
GetX相干劣势
build刷新办法极度简略!
- getx:Obx(() => Text())
- 这是我十分十分在意的一个方面,因为bloc的build刷新组件办法要传俩个泛型,加上build办法外面的俩个参数,导致一个build办法如果不应用箭头办法简写,简直占四五行,用起来切实蛋筒,导致我平时开发间接把
BlocBuilder
办法间接写在页面顶层(不提倡写顶层),一个页面只用写一次了,不必定点到处写BlocBuilder
了,手动滑稽.jpg
跨页面交互
- 这相对是GetX的一个长处!对于简单的生产环境,跨页面交互的场景,切实太常见了,GetX的跨页面交互,简直和fish_redux一样简略,爱了爱了
路由治理
- 是的,getx外部实现了路由治理,而且用起来,那叫一个简略!bloc没实现路由治理,这让我不得不去找一个star量高的路由治理框架,就抉择了fluro,然而让我不得不说,这个fluro用起来真的叫一个折磨人,每次新建一个页面,最让我抗拒的就是去写fluro路由代码,横跨几个文件来回写,真是肝疼
- GetX实现了动静路由传参,也就是说间接在命名路由上拼参数,而后能拿到这些拼在路由上的参数,也就是说用flutter写H5,间接能通过Url传值(fluro也能做到),OMG!能够无脑舍弃简单的fluro了
- 实现了全局BuildContext
- 国际化,主题实现
下面单单是build简写的劣势,就会让我思考是否去应用了,而且还能实现跨页面的性能,这还思考啥,开搞!
下来将全面的介绍GetX的应用,文章也不分篇水浏览量了,力求一文写分明,不便大家随时查阅
筹备
引入
- 首先导入GetX的插件
# getx 状态治理框架 https://pub.flutter-io.cn/packages/getget: ^3.24.0
GetX地址
- Github:jonataslaw/getx
- Pub:get
主入口配置
- 只须要将
MaterialApp
改成GetMaterialApp
即可
void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return GetMaterialApp( home: CounterGetPage(), ); }}
- 各模块导包,均应用下面包即可
import 'package:get/get.dart';
插件
吐槽下写插件的过程,理论写这种模板代码生成插件,其实也不难,网上有很多人写了范例,参考参考思路,能较快的整进去,就是有些配置比拟蛋筒。一开始抉择Plugin DevKit模式整的,都曾经写好,然而看官网文档的时候,官网文档结尾就说了:倡议应用Gradle模式开发插件,又巴拉巴拉列了一堆益处;思考好久,决定用Gradle模式重写。
这个Gradle模式,最烦的还是结尾新建我的项目的时候,那个Gradle死活下载不下来,迷信全局上网都不行,而后手动下载了Gradle,指定本地Gradle,开全局再次同步时,会下载一个较大的社区版IDEA,然而应用本地Gradle加载完,存在一个很大的BUG!main文件夹下,不会主动生成Java文件夹!我真是佛了,点击其它的文件夹,右击:New -> Plugin DevKit 竟然不会没有Action选项,差点把我劝退了,换了了七八个版本IDEA试了都不行!Action选项出不来,过了俩天后,早晨无心尝试在main文件夹上面新建了一个Java文件,而后在这个java文件上右击:New -> Plugin DevKit,Action选项呈现了!真几把佛了。。。
还有个巨坑的问题,在Gradle模式下开发插件,把模板代码文件放在main文件下、放在src下、放在根目录下,都获取不到文件外面的内容,这个真是坑了我不少工夫,搜了很多博客,都发现没写这个问题,官网文档范例看了几遍也没发现有啥阐明,起初找到了一个三年前的我的项目,翻了翻代码发现,所有的资源文件都必须放在resources文件夹下,能力读取到文件内容。。。我勒个去。。。
阐明
插件地址
- Github:getx_template
- Jetbrains:getx_template
插件成果
- 看下插件应用的效果图吧,款式参考了fish_redux插件款式
- 有一些可抉择的性能,所以做成多按钮的款式,大家能够依照本人的需要进行操作
说下插件的性能含意
Model:生成GetX的模式,
- Default:默认模式,生成三个文件:state,logic,view
- Easy:简略模式,生成三个文件:logic,view
Function:性能抉择
- useFolder:应用文件,抉择后会生成文件夹,大驼峰命名主动转换为:小写+下划线
- usePrefix:应用前缀,生成的文件前加上前缀,前缀为:大驼峰命名主动转换为:小写+下划线
- Module Name:模块的名称,请应用大驼峰命名
效果图
- 来看下应用的效果图
装置
- 在设置外面抉择:Plugins ---> 输出“getx”搜寻 ---> 抉择名字为:“GeX” ---> 而后装置 ---> 最初记得点击下“Apply”
- 如果在应用该插件的过程中有什么问题,请在该项目标github上给我提issue,我看到后,会尽快解决
计数器
效果图
- 体验一下
实现
首页,当然是实现一个简略的计数器,来看GetX怎么将逻辑层和界面层解耦的
来应用插件生成下简略文件
- 模式抉择:Easy
- 性能抉择:useFolder
来看下生成的默认代码,默认代码非常简略,具体解释放在俩种状态治理里
- logic
import 'package:get/get.dart';class CounterGetLogic extends GetxController {}
- view
import 'package:flutter/material.dart';import 'package:get/get.dart';import 'logic.dart';class CounterGetPage extends StatelessWidget { final CounterGetLogic logic = Get.put(CounterGetLogic()); @override Widget build(BuildContext context) { return Container(); }}
响应式状态治理
当数据源变动时,将主动执行刷新组件的办法
logic层
- 因为是解决页面逻辑的,加上Controller单词过长,也避免和Flutter自带的一些控件控制器弄混,所以该层用
logic
结尾,这里就定为了logic
层,当然这点随集体动向,写Event,Controller均可 - 这里变量数值后写
.obs
操作,是阐明定义了该变量为响应式变量,当该变量数值变动时,页面的刷新办法将主动刷新;根底类型,List,类都能够加.obs
,使其变成响应式变量
- 因为是解决页面逻辑的,加上Controller单词过长,也避免和Flutter自带的一些控件控制器弄混,所以该层用
class CounterGetLogic extends GetxController { var count = 0.obs; ///自增 void increase() => ++count;}
view层
这中央获取到Logic层的实例后,就可进行操作了,大家可能会想:WTF,为什么实例的操作放在build办法里?逗我呢?--------- 理论不然,stl是无状态组件,阐明了他就不会被二次重组,所以实例操作只会被执行一次,而且Obx()办法是能够刷新组件的,完满解决刷新组件问题了
class CounterGetPage extends StatelessWidget { @override Widget build(BuildContext context) { CounterGetLogic logic = Get.put(CounterGetLogic()); return Scaffold( appBar: AppBar(title: const Text('GetX计数器')), body: Center( child: Obx( () => Text('点击了 ${logic.count.value} 次', style: TextStyle(fontSize: 30.0)), ), ), floatingActionButton: FloatingActionButton( onPressed: () => logic.increase(), child: const Icon(Icons.add), ), ); }}
当然,也能够这样写
class CounterGetPage extends StatelessWidget { final CounterGetLogic logic = Get.put(CounterGetLogic()); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('GetX计数器')), body: Center( child: Obx( () => Text('点击了 ${logic.count.value} 次', style: TextStyle(fontSize: 30.0)), ), ), floatingActionButton: FloatingActionButton( onPressed: () => logic.increase(), child: const Icon(Icons.add), ), ); }}
- 能够发现刷新组件的办法极其简略:
Obx()
,这样能够欢快的到处写定点刷新操作了
Obx()办法刷新的条件
- 只有当响应式变量的值发生变化时,才会会执行刷新操作,当某个变量初始值为:“test”,再赋值为:“test”,并不会执行刷新操作
- 当你定义了一个响应式变量,该响应式变量扭转时,包裹该响应式变量的Obx()办法才会执行刷新操作,其它的未包裹该响应式变量的Obx()办法并不会执行刷新操作,Cool!
来看下如果把整个类对象设置成响应类型,如何实现更新操作呢?
- 上面解释来自官网README文档
- 这里尝试了下,将整个类对象设置为响应类型,当你扭转了类其中一个变量,而后执行更新操作,
只有包裹了该响应类变量的Obx(),都会履行刷新操作
,将整个类设置响应类型,须要结合实际场景应用
// model// 咱们将使整个类成为可察看的,而不是每个属性。class User() { User({this.name = '', this.age = 0}); String name; int age;}// controllerfinal user = User().obs;//当你须要更新user变量时。user.update( (user) { // 这个参数是你要更新的类自身。 user.name = 'Jonny'; user.age = 18;});// 更新user变量的另一种形式。user(User(name: 'João', age: 35));// viewObx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}")) // 你也能够不应用.value来拜访模型值。 user().name; // 留神是user变量,而不是类变量(首字母是小写的)。
简略状态治理
GetBuilder:这是一个极其笨重的状态管理器,占用资源极少!
- logic:先来看看logic层
class CounterEasyGetLogic extends GetxController { var count = 0; void increase() { ++count; update(); }}
- view
class CounterEasyGetPage extends StatelessWidget { final CounterEasyGetLogic logic = Get.put(CounterEasyGetLogic()); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('计数器-简略式')), body: Center( child: GetBuilder<CounterEasyGetLogic>( builder: (logicGet) => Text( '点击了 ${logicGet.count} 次', style: TextStyle(fontSize: 30.0), ), ), ), floatingActionButton: FloatingActionButton( onPressed: () => logic.increase(), child: const Icon(Icons.add), ), ); }}
剖析下:GetBuilder这个办法
- init:尽管上述代码没用到,然而,这个参数是存在在GetBuilder中的,因为在加载变量的时候就应用
Get.put()
生成了CounterEasyGetLogic
对象,GetBuilder会主动查找该对象,所以,就能够不应用init参数 - builder:办法参数,领有一个入参,类型便是GetBuilder所传入泛型的类型
- initState,dispose等:GetBuilder领有StatefulWidget所有周期回调,能够在相应回调内做一些操作
- init:尽管上述代码没用到,然而,这个参数是存在在GetBuilder中的,因为在加载变量的时候就应用
总结
剖析
GetBuilder
外部实际上是对StatefulWidget的封装,所以占用资源极小- 响应式变量,因为应用的是
StreamBuilder
,会耗费肯定资源
应用场景
- 一般来说,对于大多数场景都是能够应用响应式变量的
- 然而,在一个蕴含了大量对象的List,都应用响应式变量,将生成大量的
StreamBuilder
,必将对内存造成较大的压力,该状况下,就要思考应用简略状态治理了
跨页面交互
跨页面交互,在简单的场景中,是十分重要的性能,来看看GetX怎么实现跨页面事件交互的
效果图
- 体验一下
- Cool,这才是真正的跨页面交互!上级页面能随便调用下级页面事件,且敞开页面后,下次重进,数据也很天然重置了(全局Bloc不会重置,须要手动重置)
实现
页面一
惯例代码
logic
- 这里的自增事件,是供其它页面调用的,该页面自身没应用
class JumpOneLogic extends GetxController { var count = 0.obs; ///跳转到跨页面 void toJumpTwo() { Get.toNamed(RouteConfig.jumpTwo); } ///跳转到跨页面 void increase() => count++;}
view
- 此处就一个显示文字和跳转性能
class JumpOnePage extends StatelessWidget { /// 应用Get.put()实例化你的类,使其对当下的所有子路由可用。 final JumpOneLogic logic = Get.put(JumpOneLogic()); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar(title: Text('跨页面-One')), floatingActionButton: FloatingActionButton( onPressed: () => logic.toJumpTwo(), child: const Icon(Icons.arrow_forward_outlined), ), body: Center( child: Obx( () => Text('跨页面-Two点击了 ${logic.count.value} 次', style: TextStyle(fontSize: 30.0)), ), ), ); }}
页面二
这个页面就是重点了,将演示怎么调用前一个页面的事件
- logic
class JumpTwoLogic extends GetxController { var count = 0.obs; ///跳转到跨页面 void increase() => count++;}
view
- 加号的点击事件,点击时,能实现俩个页面数据的变换
- 重点来了,这里通过
Get.find()
,获取到了之前实例化GetXController,获取某个模块的GetXController后就很好做了,能够通过这个GetXController去调用相应的事件,也能够通过它,拿到该模块的数据!
class JumpTwoPage extends StatelessWidget { final JumpOneLogic oneLogic = Get.find(); final JumpTwoLogic twoLogic = Get.put(JumpTwoLogic()); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar(title: Text('跨页面-Two')), floatingActionButton: FloatingActionButton( onPressed: () { oneLogic.increase(); twoLogic.increase(); }, child: const Icon(Icons.add), ), body: Center( child: Obx( () => Text('跨页面-Two点击了 ${twoLogic.count.value} 次', style: TextStyle(fontSize: 30.0)), ), ), ); }}
总结
GetX这种的跨页面交互事件,真的是非常简单了,侵入性也十分的低,不须要在主入口配置什么,在简单的业务场景下,这样简略的跨页面交互方式,就能实现很多事了
进阶吧!计数器
咱们可能会遇到过很多简单的业务场景,在简单的业务场景下,单单某个模块对于变量的初始化操作可能就十分多,在这个时候,如果还将state(状态层)和logic(逻辑层)写在一起,保护起来可能看的比拟晕,这里将状态层和逻辑层进行一个拆分,这样在略微大一点的我的项目里应用GetX,也能保障构造足够清晰了!
在这里就持续用计数器举例吧!
实现
此处须要划分三个构造了:state(状态层),logic(逻辑层),view(界面层)
这里应用插件生成下模板代码
- Model:抉择Default(默认)
- Function:useFolder(默认中)
来看下生成的模板代码
- state
class CounterHighGetState { CounterHighGetState() { ///Initialize variables }}
- logic
import 'package:get/get.dart';import 'state.dart';class CounterHighGetLogic extends GetxController { final state = CounterHighGetState();}
- view
import 'package:flutter/material.dart';import 'package:get/get.dart';import 'logic.dart';import 'state.dart';class CounterHighGetPage extends StatelessWidget { final CounterHighGetLogic logic = Get.put(CounterHighGetLogic()); final CounterHighGetState state = Get.find<CounterHighGetLogic>().state; @override Widget build(BuildContext context) { return Container(); }}
为什么写成这样三个模块,须要把State独自提出来,请速速浏览下方
革新
state
- 这里能够发现,count类型应用的是
RxInt
,没有应用var
,应用该变量类型的起因,此处是将所有的操作都放在构造函数外面初始化,如果间接应用var
没有立马赋值,是无奈推导为Rx
类型,所以这里间接定义为RxInt
,理论很简略,根底类型将结尾字母大写,而后加上Rx
前缀即可 - 实际上间接应用
var
也是能够的,然而,应用该响应变量的时候.value
无奈提醒,须要本人手写,所以还是老老实实的写明Rx具体类型吧 - 具体可查看:申明响应式变量
- 这里能够发现,count类型应用的是
class CounterHighGetState { RxInt count; CounterHighGetState() { count = 0.obs; }}
logic
- 逻辑层就比较简单,须要留神的是:开始时须要实例化状态类
class CounterHighGetLogic extends GetxController { final state = CounterHighGetState(); ///自增 void increase() => ++state.count;}
view
- 实际上view层,和之前的简直没区别,区别的是把状态层给独立进去了
- 因为
CounterHighGetLogic
被实例化,所以间接应用Get.find<CounterHighGetLogic>()
就能拿到刚刚实例化的逻辑层,而后拿到state,应用独自的变量接管下 - ok,此时:logic只专一于触发事件交互,state只专一数据
class CounterHighGetPage extends StatelessWidget { final CounterHighGetLogic logic = Get.put(CounterHighGetLogic()); final CounterHighGetState state = Get.find<CounterHighGetLogic>().state; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('计数器-响应式')), body: Center( child: Obx( () => Text('点击了 ${state.count.value} 次', style: TextStyle(fontSize: 30.0)), ), ), floatingActionButton: FloatingActionButton( onPressed: () => logic.increase(), child: const Icon(Icons.add), ), ); }}
比照
看了下面的革新,屏幕前的你可能想吐槽了:坑比啊,之前简简单单的逻辑层,被拆成俩个,还搞得这么麻烦,你是猴子请来的逗比吗?大家先别急着吐槽,当业务过于简单,state层,也是会保护很多货色的,让我看看上面的一个小栗子,上面实例代码是不能间接运行的,想看具体运行代码,请查看我的项目:flutter_use
- state
class MainState { ///抉择index - 响应式 RxInt selectedIndex; ///管制是否开展 - 响应式 RxBool isUnfold; ///分类按钮数据源 List<BtnInfo> list; ///Navigation的item信息 List<BtnInfo> itemList; ///PageView页面 List<Widget> pageList; PageController pageController; MainState() { //初始化index selectedIndex = 0.obs; //默认不开展 isUnfold = false.obs; //PageView页面 pageList = [ keepAliveWrapper(FunctionPage()), keepAliveWrapper(ExamplePage()), keepAliveWrapper(Center(child: Container())), ]; //item栏目 itemList = [ BtnInfo( title: "性能", icon: Icon(Icons.bubble_chart), ), BtnInfo( title: "范例", icon: Icon(Icons.opacity), ), BtnInfo( title: "设置", icon: Icon(Icons.settings), ), ]; //页面控制器 pageController = PageController(); }}
- logic
class MainLogic extends GetxController { final state = MainState(); ///切换tab void switchTap(int index) { state.selectedIndex.value = index; } ///是否开展侧边栏 void onUnfold(bool unfold) { state.isUnfold.value = !state.isUnfold.value; }}
- view
class MainPage extends StatelessWidget { final MainLogic logic = Get.put(MainLogic()); final MainState state = Get.find<MainLogic>().state; @override Widget build(BuildContext context) { return BaseScaffold( backgroundColor: Colors.white, body: Row(children: [ ///侧边栏区域 Obx( () => SideNavigation( selectedIndex: state.selectedIndex.value, sideItems: state.itemList, onItem: (index) { logic.switchTap(index); state.pageController.jumpToPage(index); }, isUnfold: state.isUnfold.value, onUnfold: (unfold) { logic.onUnfold(unfold); }, ), ), ///Expanded占满剩下的空间 Expanded( child: PageView.builder( physics: NeverScrollableScrollPhysics(), itemCount: state.pageList.length, itemBuilder: (context, index) => state.pageList[index], controller: state.pageController, ), ) ]), ); }}
从下面能够看出,state层外面的状态曾经较多了,当某些模块波及到大量的:提交表单数据,跳转数据,展现数据等等,state层的代码会相当的多,置信我,真的是十分多,一旦业务产生变更,还要常常保护批改,就蛋筒了
在简单的业务下,将状态层(state)和业务逻辑层(logic)离开,相对是个理智的行动
最初
- 该模块的效果图就不放了,和下面计数器成果截然不同,想体验一下,可点击:[体验一下]()
- 简略的业务模块,能够应用俩层构造:logic,view;简单的业务模块,举荐应用三层构造:state,logic,view
路由治理
GetX实现了一套用起来非常简略的路由治理,能够应用一种极其简略的形式导航,也能够应用命名路由导航
简略路由
- 主入口配置
void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return GetMaterialApp( home: MainPage(), ); }}
路由的相干应用
- 应用是非常简单,应用Get.to()之类api即可,此处简略演示,具体api阐明,放在本节结尾
//跳转新页面Get.to(SomePage());
命名路由导航
这里是举荐应用命名路由导航的形式
- 对立治理起了所有页面
- 在app中可能感触不到,然而在web端,加载页面的url地址就是命名路由你所设置字符串,也就是说,在web中,能够间接通过url导航到相干页面
上面阐明下,如何应用
- 首先,在主入口出配置下
void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return GetMaterialApp( initialRoute: RouteConfig.main, getPages: RouteConfig.getPages, ); }}
RouteConfig类
- 上面是我的相干页面,和其映射的页面,请依据本人的页面进行相干编写
class RouteConfig{ ///主页面 static final String main = "/"; ///dialog页面 static final String dialog = "/dialog"; ///bloc计数器模块 static final String counter = "/counter"; ///测试布局页面 static final String testLayout = "/testLayout"; ///演示SmartDialog控件 static final String smartDialog = "/smartDialog"; ///Bloc跨页面传递事件 static final String spanOne = "/spanOne"; static final String spanTwo = "/spanOne/spanTwo"; ///GetX 计数器 跨页面交互 static final String counterGet = "/counterGet"; static final String jumpOne = "/jumpOne"; static final String jumpTwo = "/jumpOne/jumpTwo"; ///别名映射页面 static final List<GetPage> getPages = [ GetPage(name: main, page: () => MainPage()), GetPage(name: dialog, page: () => Dialog()), GetPage(name: counter, page: () => CounterPage()), GetPage(name: testLayout, page: () => TestLayoutPage()), GetPage(name: smartDialog, page: () => SmartDialogPage()), GetPage(name: spanOne, page: () => SpanOnePage()), GetPage(name: spanTwo, page: () => SpanTwoPage()), GetPage(name: counterGet, page: () => CounterGetPage()), GetPage(name: jumpOne, page: () => JumpOnePage()), GetPage(name: jumpTwo, page: () => JumpTwoPage()), ];}
路由API
请留神命名路由,只须要在api结尾加上Named
即可,举例:
- 默认:Get.to(SomePage());
- 命名路由:Get.toNamed(“/somePage”);
具体Api介绍,上面内容来自GetX的README文档,进行了相干整顿
- 导航到新的页面
Get.to(NextScreen());Get.toNamed("/NextScreen");
- 敞开SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)敞开的货色
Get.back();
- 进入下一个页面,但没有返回上一个页面的选项(用于SplashScreens,登录页面等)
Get.off(NextScreen());Get.offNamed("/NextScreen");
- 进入下一个界面并勾销之前的所有路由(在购物车、投票和测试中很有用)
Get.offAll(NextScreen());Get.offAllNamed("/NextScreen");
- 发送数据到其它页面
只有发送你想要的参数即可。Get在这里承受任何货色,无论是一个字符串,一个Map,一个List,甚至一个类的实例。
Get.to(NextScreen(), arguments: 'Get is the best');Get.toNamed("/NextScreen", arguments: 'Get is the best');
在你的类或控制器上:
print(Get.arguments);//print out: Get is the best
- 要导航到下一条路由,并在返回后立刻接管或更新数据
var data = await Get.to(Payment());var data = await Get.toNamed("/payment");
- 在另一个页面上,发送前一个路由的数据
Get.back(result: 'success');// 并应用它,例:if(data == 'success') madeAnything();
- 如果你不想应用GetX语法,只有把 Navigator(大写)改成 navigator(小写),你就能够领有规范导航的所有性能,而不须要应用context,例如:
// 默认的Flutter导航Navigator.of(context).push( context, MaterialPageRoute( builder: (BuildContext context) { return HomePage(); }, ),);// 应用Flutter语法取得,而不须要context。navigator.push( MaterialPageRoute( builder: (_) { return HomePage(); }, ),);// get语法Get.to(HomePage());
动静网页链接
- 这是一个十分重要的性能,在web端,能够
保障通过url传参数到页面
里
Get提供高级动静URL,就像在Web上一样。Web开发者可能曾经在Flutter上想要这个性能了,Get也解决了这个问题。
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
在你的controller/bloc/stateful/stateless类上:
print(Get.parameters['id']);// out: 354print(Get.parameters['name']);// out: Enzo
你也能够用Get轻松接管NamedParameters。
void main() { runApp( GetMaterialApp( initialRoute: '/', getPages: [ GetPage( name: '/', page: () => MyHomePage(), ), GetPage( name: '/profile/', page: () => MyProfile(), ), //你能够为有参数的路由定义一个不同的页面,也能够为没有参数的路由定义一个不同的页面,然而你必须在不接管参数的路由上应用斜杠"/",就像下面说的那样。 GetPage( name: '/profile/:user', page: () => UserProfile(), ), GetPage( name: '/third', page: () => Third(), transition: Transition.cupertino ), ], ) );}
发送命名路由数据
Get.toNamed("/profile/34954");
在第二个页面上,通过参数获取数据
print(Get.parameters['user']);// out: 34954
当初,你须要做的就是应用Get.toNamed()来导航你的命名路由,不须要任何context(你能够间接从你的BLoC或Controller类中调用你的路由),当你的应用程序被编译到web时,你的路由将呈现在URL中。
最初
相干地址
- 文中DEMO地址:flutter_use
- GetX插件地址:getx_template
系列文章
引流了,手动滑稽.jpg
- Dialog解决方案,墙裂举荐
一种更优雅的Flutter Dialog解决方案
- 状态治理篇
fish_redux应用详解---看完就会用!
flutter_bloc应用解析---骚年,你还在手搭bloc吗!