全栈工程师?
嗯.....目前并不是!

Flutter状态管理终极方案GetX第一篇——路由

undefined
undefined
undefined
undefined
代码示例

前言

GetX 是 Flutter 上的一个轻量且强大的解决方案:高性能的状态管理、智能的依赖注入和便捷的路由管理。

为什么是 GetX,而不是 BLoC、MobX、Provider?

BLoC 非常安全和高效,但是对于初学者来说非常复杂,即使学会,样板代码也很多。

MobX 比 BLoC 更容易,而且是响应式的,但是需要使用一个代码生成器,需要等很久,这降低了生产力。

GetX我喜欢的地方:

  • 轻量。模块单独编译,没用到的功能不会编译进我们的代码。
  • 语法简洁。个人非常喜欢,显而易见且实用,比如路由摆脱了 context 的依赖,Get.to(SomePage())就能导航到新路由。
  • 性能。Provider、BLoC 等只能在父子组件保存状态,同层级模块状态管理需要全局处理,存活在整个应用生命周期。而 GetX 可以随时添加控制器和删除控制器,并且会自动释放使用完的控制器。
  • 依赖注入。提供依赖注入功能,代码层级可以完全分离,甚至依赖注入的代码也是分离的。
  • 丰富的api。许多复杂的操作,使用 GetX 就会有简单的实现。

有的同学看过我写的Flutter状态管理provider的使用和封装,讲解了 Provider 的使用,其实在使用过程中发现了许多痛点,最致命的是 Provider 使用InheritedWidget 来传递相同的监听器,这意味着对其 ChangeNotifier 类的任何访问都必须在父子widget树内。非父子组件的状态管理问题,需要借助别的手段(eventbus,全局,单例),十分痛苦,在改用GetX后,越来越舒服了。


路由

普通路由导航

打开到新的页面:

Get.to(NextScreen());

对应原生路由:

    Navigator.push(context, MaterialPageRoute<<span class="hljs-keyword">void</span>>(
      builder: (BuildContext context) {
        <span class="hljs-keyword">return</span> NextScreen();
      },
    ));

返回:

Get.back();

对应原生路由:

    Navigator.pop(context);

打开新页面,并且用新页面替换旧页面(删除旧页面):

Get.off(NextScreen());

对应原生路由:

 Navigator.pushReplacement(context, MaterialPageRoute<<span class="hljs-keyword">void</span>>(
      builder: (BuildContext context) {
        <span class="hljs-keyword">return</span> NextScreen();
      },
    ));

打开新页面并删除之前的所有路由:

Get.offAll(NextScreen());

对应原生路由:

   Navigator.pushAndRemoveUntil(
      context,
      MaterialPageRoute<<span class="hljs-keyword">void</span>>(
        builder: (BuildContext context) {
          <span class="hljs-keyword">return</span> NextScreen();
        },
      ),
      (Route<<span class="hljs-built_in">dynamic</span>> route) => <span class="hljs-keyword">false</span>,
    );

导航到新页面,在返回时接收返回数据:

<span class="hljs-keyword">var</span> data = <span class="hljs-keyword">await</span> Get.to(NextScreen());

对应原生路由:

    <span class="hljs-keyword">var</span> data = <span class="hljs-keyword">await</span>  Navigator.push(context, MaterialPageRoute<<span class="hljs-keyword">void</span>>(
      builder: (BuildContext context) {
        <span class="hljs-keyword">return</span> NextScreen();
      },
    ));

带返回值返回前一个路由,配合上面使用:

Get.back(result: <span class="hljs-string">'success'</span>);

对应原生路由:

 Navigator.pop(context, <span class="hljs-string">'success'</span>);

别名路由导航

  1. 声明别名:
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Routes</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> Initial = <span class="hljs-string">'/'</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> NextScreen = <span class="hljs-string">'/NextScreen'</span>;

}
  1. 注册路由表:
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppPages</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> pages = [
    GetPage(
      name: Routes.Initial,
      page: () => HomePage(),
    ),
    GetPage(
      name: Routes.NextScreen,
      page: () => NextScreen(),
    ),
  ];
}
  1. 替换MaterialApp为GetMaterialApp:
void main() {
  runApp(GetMaterialApp(
    debugShowCheckedModeBanner: false,
    initialRoute: '/',
    theme: appThemeData,
    defaultTransition: Transition.fade,
    getPages: AppPages.pages,
    home: HomePage(),
  ));
}

使用

导航到下一个页面:

Get.toNamed(Routes.NextScreen);

导航到下一个页面并删除前一个页面:

Get.offNamed(Routes.NextScreen);

导航到下一个页面并删除以前所有的页面:

Get.offAllNamed(Routes.NextScreen);

发送数据到别名路由:

Get在这里接受任何东西,无论是一个字符串,一个Map,一个List,甚至一个类的实例。

Get.toNamed(Routes.NextScreen, arguments: '新垣结衣');

获取参数:

String name=Get.arguments;

动态网页链接:

像web一样携带参数,适合前端开发的风格。

Get.offAllNamed(/NextScreen?device=phone&id=354&name=Enzo);

获取参数:

int id = Get.parameters['id'];
// out: 354
String name=Get.parameters['name'];

还可以这样定义路由别名:

       GetPage(
        name: '/profile/:user',
        page: () => UserProfile(),
      ),

导航:

Get.toNamed(/profile/34954);

在第二个页面上,通过参数获取数据

print(Get.parameters['user']);
// out: 34954

中间件

在跳转前做些事情,比如判断是否登录,可以使用routingCallback来实现:

GetMaterialApp(
  routingCallback: (routing) {
    if(routing.current == '/second'){
     // 如果登录。。。
    }
  }
)

小部件导航

SnackBars

弹出:

Get.snackbar('Hi', 'i am a modern snackbar');

对应原生写法:

final snackBar = SnackBar(
  content: Text('Hi!'),
  action: SnackBarAction(
    label: 'I am a old and ugly snackbar',
    onPressed: (){}
  ),
);

//用Flutter创建一个简单的SnackBar,你必须获得Scaffold的context,或者你必须使用一个GlobalKey附加到你的Scaffold上。

Scaffold.of(context).showSnackBar(snackBar);

Dialogs

打开一个默认的Dialog:

Get.defaultDialog(
  onConfirm: () => print(Ok),
  middleText: Dialog made in 3 lines of code
);

打开自定义的Dialog:

Get.dialog(YourDialogWidget());

BottomSheets

Get.bottomSheet类似于showModalBottomSheet,但不需要context:

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: () => {},
        ),
      ],
    ),
  )
);
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《Flutter状态管理终极方案GetX第一篇——路由》
文章链接:https://www.pmbear.com/archives/11370
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

大前端WP主题 更专业 更方便

联系我们联系我们