乐趣区

关于android:Flutter-GetX使用简洁的魅力

前言

应用 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/get
get: ^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,使其变成响应式变量
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;
}

// controller
final user = User().obs;
// 当你须要更新 user 变量时。user.update((user) { // 这个参数是你要更新的类自身。user.name = 'Jonny';
    user.age = 18;
});
// 更新 user 变量的另一种形式。user(User(name: 'João', age: 35));

// view
Obx(()=> 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 所有周期回调,能够在相应回调内做一些操作

总结

剖析

  • 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 具体类型吧
    • 具体可查看:申明响应式变量
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: 354
print(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 吗!

退出移动版