Flutter 与原生交互之路由跳转封装文档

Flutter 与原生交互之路由跳转封装文档

Flutter项目中,当需要与原生(安卓和iOS)进行交互,通过点击按钮向原生传递路由信息及数据,让原生进行对应路由跳转时,为了提高代码的复用性和可维护性,对相关功能进行封装是很有必要的。以下是在Flutter端进行封装的详细步骤及示例代码。

一、创建MethodChannel与封装类

  1. 首先,在Flutter项目中创建一个专门用于与原生通信的MethodChannel,并定义好通道名称,该名称需与原生端保持一致。例如:

    1
    2
    3
    4
    import 'package:flutter/services.dart';
    class NativeCommunication {
    static const platform = MethodChannel('route_channel');
    }

    这里将通道名称定义为'route_channel',你可根据实际项目需求进行调整。

  2. 接着创建一个用于封装向原生发送路由信息的类,假设名为RouteSender

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class RouteSender {
    Future<void> sendRouteToNative(String route, Map<String, dynamic> data) async {
    try {
    await NativeCommunication.platform.invokeMethod('jumpToRoute', {
    'route': route,
    'data': data,
    });
    } on PlatformException catch (e) {
    print("调用原生方法出错: ${e.message}");
    }
    }
    }

    二、使用封装类

    在需要向原生传递路由和数据的地方,比如某个按钮的点击事件处理函数中,使用封装好的RouteSender类。示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import 'package:flutter/material.dart';
    class MyWidget extends StatefulWidget {
    @override
    _MyWidgetState createState() => _MyWidgetState();
    }
    class _MyWidgetState extends State<MyWidget> {
    final routeSender = RouteSender();
    Future<void> _onButtonClick() async {
    String route = "/new_page"; // 这里定义要传递的路由,可根据实际情况修改
    Map<String, dynamic> data = {"key": "value"}; // 定义要传递的相关数据,按需调整
    await routeSender.sendRouteToNative(route, data);
    }
    @override
    Widget build(BuildContext context) {
    return ElevatedButton(
    onPressed: _onButtonClick,
    child: Text('传递路由信息给原生'),
    );
    }
    }

    在上述代码中,当按钮被点击时,_onButtonClick函数会被触发,它首先定义好要传递的路由"/new_page"和相关数据{"key": "value"},然后调用RouteSender类中的sendRouteToNative方法,将路由和数据通过已创建的MethodChannel发送给原生。通过这样的封装,在项目的其他地方,如果也有类似向原生传递路由信息的需求,只需引入RouteSender类并调用相应方法即可,大大提高了代码的复用性和可维护性。

  • 注意:确保在Flutter项目的pubspec.yaml文件中,相关依赖(如flutter/services.dart)已正确引入,并且原生端的通道名称、接收方法及后续处理逻辑与Flutter端准确对应,才能保证通信与跳转功能的正常实现。

三、安卓端封装

(一)创建工具类 RouteUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel.Result;
import java.util.Map;
public class RouteUtils {
// 根据不同路由进行相应的Activity跳转,这里可根据实际项目扩展更多路由及对应跳转逻辑
public static void handleRouteJump(@NonNull Context context, @NonNull MethodCall call, @NonNull Result result) {
String route = call.argument("route");
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) call.argument("data");
if (route.equals("/new_page")) {
Intent intent = new Intent(context, NewPageActivity.class);
if (data!= null) {
for (String key : data.keySet()) {
intent.putExtra(key, (String) data.get(key));
}
}
context.startActivity(intent);
result.success("路由跳转成功");
} else if (route.equals("/another_page")) {
// 假设还有另一个路由对应的Activity跳转逻辑,可按如下方式添加
Intent intent = new Intent(context, AnotherPageActivity.class);
if (data!= null) {
// 处理传递的数据添加到Intent中,和上面类似
}
context.startActivity(intent);
result.success("路由跳转成功");
} else {
result.notImplemented();
}
}
}

这个工具类的核心方法 handleRouteJump 接收 Flutter 端通过 MethodChannel 传递过来的方法调用信息(包含路由 route 和数据 data),根据不同的路由字符串,创建对应的 Intent 并启动相应的 Activity,同时可以将传递的数据添加到 Intent 中。如果路由不匹配已定义的路由,则返回 notImplementedFlutter 端。

(二)在 MainActivity 中使用封装类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "route_channel";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
if (call.method.equals("jumpToRoute")) {
RouteUtils.handleRouteJump(MainActivity.this, call, result);
} else {
result.notImplemented();
}
});
}
}

MainActivityconfigureFlutterEngine 方法中,当接收到 Flutter 端名为 jumpToRoute 的方法调用时,直接调用 RouteUtils 类的 handleRouteJump 方法来处理路由跳转逻辑,这样使得 MainActivity 中的代码更加简洁,将复杂的路由判断和跳转逻辑封装到了 RouteUtils 类中,提高了代码的可维护性。

四、iOS 端封装

(一)创建 RouteHandler.swift 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import UIKit
import Flutter
class RouteHandler {
// 根据不同路由进行相应的视图控制器切换等操作,可根据实际项目扩展更多路由及对应逻辑
static func handleRouteJump(_ call: FlutterMethodCall, _ result: FlutterMethodChannel.Result) {
if let route = call.arguments as? [String: Any],
let routeString = route["route"] as? String,
let data = route["data"] as? [String: Any] {
switch routeString {
case "/new_page":
let newViewController = NewPageViewController()
if let key = data.keys.first, let value = data[key] as? String {
newViewController.data = value
}
let controller = UIApplication.shared.windows.first?.rootViewController as! FlutterViewController
controller.present(newViewController, animated: true, completion: nil)
result("路由跳转成功", nil)
case "/another_page":
// 假设还有另一个路由对应的视图控制器切换逻辑,可按如下方式添加
let anotherViewController = AnotherPageViewController()
// 处理传递的数据添加到视图控制器等相关操作,和上面类似
let controller = UIApplication.shared.windows.first?.rootViewController as! FlutterViewController
controller.present(anotherViewController, animated: true, completion: nil)
result("路由跳转成功", nil)
default:
result(FlutterError(code: "未实现的路由", nil), nil)
}
} else {
result(FlutterError(code: "参数解析错误", nil), nil)
}
}
}

RouteHandler 类的 handleRouteJump 方法负责处理 Flutter 端传递过来的路由和数据。它首先解析获取到的路由字符串和数据,然后根据不同的路由进行相应的视图控制器切换操作,如创建新的视图控制器并展示,同时将传递的数据传递给新的视图控制器。如果路由不匹配或参数解析错误,会返回相应的 FlutterErrorFlutter 端。

(二)在 AppDelegate.swift 中使用封装类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import UIApplicationMain
import Flutter
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
let CHANNEL = "route_channel"
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { (call, result) in
if call.method == "jumpToRoute" {
RouteHandler.handleRouteJump(call, result)
} else {
result(FlutterError(code: "未实现的方法", nil), nil)
}
}
return super.application(application, didFinishLaunchingWithptions: launchOptions)
}
}

AppDelegateapplication 方法中,当接收到 FlutterjumpToRoute 的方法调用时,调用 RouteHandler 类的 handleRouteJump 方法来处理路由跳转逻辑,使得 AppDelegate 中的代码简洁明了,将路由处理逻辑封装到专门的类中,方便后续的扩展和维护。


通过以上对安卓和 iOS 端的封装,在 Flutter 项目与原生交互的路由跳转场景中,能够更加高效地开发和管理代码,当有新的路由需求或者需要在其他地方复用路由跳转逻辑时,只需在对应的封装类中进行修改和扩展即可。