Flutter早知道 - Named Router能够传参了!

本文中涉及部分非Flutter的stable版本(2019年2月25日 为止),您可查阅Flutter相关文档查看新功能是否同步的stable分支或者切换其余分支(如master)中体验git

引言

在咱们使用Flutter开发App时,路由是必须用到的。github

Flutter提供了两种方式进行路由,分别是 Navigator.push() () 以及 Navigator.pushNamed() ()。markdown

对于这两种方式各有各的优势与缺点:app

  1. Navigator.push()
  • 优势:动态、自由度大,能够以不一样的动画方式跳转到新页面,且能够传递参数到新的页面。
  • 缺点:会形成代码冗余,并且不便于代码维护。(固然你能够将其进行封装 这里不讨论这一点)
  1. Navigator.pushNamed()
  • 优势:一句话就能实现页面的跳转与目前大多数框架的方式类似。
  • 缺点:不能传递参数!不能传递参数!不能传递参数!

选择

在实际开发运用中,咱们也是更加倾向于Named路由方式。框架

可是惟一不足之处就是它不支持传递参数,这一点实在是使人抓狂。less

其实在Flutter的Issues中16年就有人提出这个问题,可是这个Issue一直到今年才有PR被提交(目前为止这个功能仅仅被合并进master分支并无同步到bate或者stable)ide

上手体验

  1. 首先咱们要切到master分支下

执行 flutter channel master 而后再运行命令flutter upgrade保证你处于最新的版本。便可切换到master分支下优化

  1. 建立一个Flutter项目
  2. 这里咱们在main.dart中略做修改
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.title),
      ),
      body: Center(
        child: GestureDetector(
          onTap: (){
            // TODO
          },
          child: Text("go next page with params"),
        ),
      ),
    );
  }
}


复制代码
  1. 添加第二个页面page.dart
import 'package:flutter/material.dart';

class Page extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Text("hi this is next page"),
      ),
    );
  }
}
复制代码
  1. 添加路由并跳转同时传递参数 main.dart
import 'package:flutter/material.dart';
// 引入新页面
import 'page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      // 处理Named页面跳转 传递参数
      onGenerateRoute: (RouteSettings setting) {
        if(setting.name == '/page') {
          return MaterialPageRoute(builder: (context) => Page(id: setting.arguments['id']));
        }
      },
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.title),
      ),
      body: Center(
        child: GestureDetector(
          onTap: (){
            // 进行Named页面跳转 传递参数
            Navigator.pushNamed(context, '/page', arguments: { "id": 1} );
          },
          child: Text("go next page with params"),
        ),
      ),
    );
  }
}


复制代码
  1. 页面接受参数 page.dart
import 'package:flutter/material.dart';

class Page extends StatelessWidget{
  Page({this.id});
  final int id;

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Text("hi this is next page, id is $id"),
      ),
    );
  }
}
复制代码

效果

优化

这里咱们仍是要在onGenerateRoute处理咱们的Named跳转,咱们在对他进行优化一下。动画

(目前没办法在MaterialApp的routes进行处理,缘由可见源码()())ui

源码一处:调用widget.pageRouteBuilder并传入settings(argumentssettings中)

源码二处:pageRouteBuilder被写死为构建一个MaterialPageRoute,而MaterialPageRoute中并无对settings进行传递

因此咱们只能本身在onGenerateRoute中进行处理。(但愿官网也能继续优化,emmmm拭目以待)

/** * main.dart */
import 'package:flutter/material.dart';
// 引入新页面
import 'page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // 定义路由信息
  final Map<String, Function> routes = {
    '/page': (context, {arguments}) => Page(arguments: arguments)
  };

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      // 处理Named页面跳转 传递参数
      onGenerateRoute: (RouteSettings settings) {
        // 统一处理
        final String name = settings.name;
        final Function pageContentBuilder = this.routes[name];
        if (pageContentBuilder != null) {
          final Route route = MaterialPageRoute(
              builder: (context) =>
                  pageContentBuilder(context, arguments: settings.arguments));
          return route;
        }
      },
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.title),
      ),
      body: Center(
        child: GestureDetector(
          onTap: () {
            // 进行Named页面跳转 传递参数
            Navigator.pushNamed(context, '/page', arguments: {'id': 123});
          },
          child: Text("go next page with params"),
        ),
      ),
    );
  }
}


/** * page.dart */

import 'package:flutter/material.dart';

class Page extends StatelessWidget{
  Page({this.arguments});
  final Map arguments;

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Text("hi this is next page, id is ${arguments != null ? arguments['id'] : '0'}"),
      ),
    );
  }
}

复制代码

相关代码

flutter_new_feature

相关文章
相关标签/搜索