Flutter 路由介绍及跳转传参

2,677 阅读2分钟

Flutter通过路由实现类似Android的 startActivity页面跳转.

核心类:

Route : 一个抽象的入口. 代表一个页面

Navigator : 管理Route的Widget.

页面跳转


普通路由:

跳转到下一页面

Navigator.push(context, MaterialPageRoute(builder: (context)=>TargetPage()));

返回上一页面

Navigator.pop(context);
或者
Navigator.of(context).pop();

ps: (context)=>TargetPage(),为dart的语法.相当于 (context){TargetPage();}.当方法体内只有一个语句,便可使用 =>进行简写

命名路由

1.首先定义一个 routes

return MaterialApp(
    initialRoute: "/",//有声明initialRoute就不用指定home了

    routes: {
      '/':(context)=>MainPage(),
      '/second':(context)=>TargetPage()
    },
);

2.跳转到下一个页面

Navigator.pushNamed(context, '/second');

3.返回上一个页面

Navigator.pop(context);

混合栈跳转

Native跳转到Flutter页面(以android为例):

这种跳转flutter是包裹在一个activity里

MainActivity:
Intent intent = new Intent(this,FlutterContainerActivity.class);
startActivity(intent);

FlutterContainerActivity:
@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        FlutterView flutterView = Flutter.createView(this, getLifecycle(), "defaultRoute");
        setContentView(flutterView);
}
Flutter跳转到Native:

flutter跳转到Native则要通过方法通道MethodChannel实现.

avatar

FlutterContainerActivity:
@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //初始化flutter容器
        FlutterView flutterView = Flutter.createView(this, getLifecycle(), "defaultRoute");

        //创建方法通道
        new MethodChannel(flutterView,"customName").setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall methodCall, @NonNull MethodChannel.Result result) {
                if (methodCall.method.equals("openNativePage")){
                    startActivity(new Intent(FlutterContainerActivity.this,FlutterCallActivity.class));
                    result.success(0);
                }else if(methodCall.method.equals("closeNativePage")){
                    finish();
                    result.success(0);
                }else {
                    result.notImplemented();
                }
            }
        });

        setContentView(flutterView);
    }
    
Flutter:
//获取方法通道
static const platChannel = MethodChannel("customName");

//打开Native页面
void openNativePage() async {
    await platChannel.invokeMethod('openNativePage');
}

//关闭Native页面
platChannel.invokeMethod('closeNativePage')),

路由传参


通过构造函数传参:

在目标函数定义一个构造方法

class TargetPage{
final String text;
const SecondRoute({Key key,this.text}) : super(key: key);
}

跳转下一页面

Navigator.push(context,MaterialPageRoute(builder:(context)=>TargetPage(text:"hello world")))

通过arguments传参:

这种方式类似android中通过intent传递数据的方式.而且这种方式是命名路由特有的.也就是pushNamed的第三个可选参数

@optionalTypeArgs
static Future<T> pushNamed<T extends Object>(
    BuildContext context,
    String routeName, {
    'Object arguments',
})

目标界面使用ModalRoute接收传过来的数据

 final data = ModalRoute.of(context).settings.arguments;

通过onGenerateRoute传参:

构建onGenerateRoute,onGenerateRoute相当于一个拦截器,截获信息然后分配给指定路由

onGenerateRoute: (settings) {
        print("onGenerate");

        if (settings.name == '/second') {
          return MaterialPageRoute(
              builder: (context) => TargetPage(
                    text: settings.arguments,
                  ));
        }
        
        return MaterialPageRoute(builder: (context) => MainPage());
},

跳转到下一页面

Navigator.pushNamed(context, '/second',arguments: 'hello flutter');

ps: 只有在定义的routes中找不到指定的路由,才会回调onGenerateRoute.

接收上一页面返回的数据:

如果需要像android中的startActivityForResult从目标页面获取数据并返回,该如何实现呢?

@optionalTypeArgs
static Future<T> push<T extends Object>(BuildContext context, Route<T> route) {
    return Navigator.of(context).push(route);
}

从上面我们可以看到,push其实是有返回值的,返回一个Future对象.这是一个异步结果对象,所以需要使用到async,await

void skip(BuildContext context) async{
     final resultData = await Navigator.push(context, MaterialPageRoute(builder: (context)=>TargetPage()));
     //打印结果
     print(resultData.toString());
}

目标页面返回

Navigator.pop(context,'hi~~');