一般的Flutter与原生平台的通信方式有3种:
- MethodChannel:主要用于Flutter端和原生端之间的方法调用
【常用】 - EventChannel:用于数据流的持续通信,收到消息后无法立即回复本次通信消息,通常用在原生平台主动向Flutter发送消息的场景
- BasicMessageChannel:用于传递字符串或半结构体的数据
平台端与Flutter端之间的数据类型映射表
Dart | Java | Kotlin | OC | Swift |
---|---|---|---|---|
null | null | null | nil (NSNull when nested) | nil |
bool | java.lang.Boolean | Boolean | NSNumber numberWithBool: | NSNumber(value: Bool) |
int | java.lang.Integer | Int | NSNumber numberWithInt: | NSNumber(value: Int32) |
int, if 32 bits not enough | java.lang.Long | Long | NSNumber numberWithLong: | NSNumber(value: Int) |
double | java.lang.Double | Double | NSNumber numberWithDouble: | NSNumber(value: Double) |
String | java.lang.String | String | NSString | String |
Uint8List | byte[] | ByteArray | FlutterStandardTypedData typedDataWithBytes: | FlutterStandardTypedData(bytes: Data) |
Int32List | int[] | IntArray | FlutterStandardTypedData typedDataWithInt32: | FlutterStandardTypedData(int32: Data) |
Int64List | long[] | LongArray | FlutterStandardTypedData typedDataWithInt64: | FlutterStandardTypedData(int64: Data) |
Float64List | double[] | DoubleArray | FlutterStandardTypedData typedDataWithFloat64: | FlutterStandardTypedData(float64: Data) |
List | java.util.ArrayList | List | NSArray | Array |
Map | java.util.HashMap | HashMap | NSDictionary | Dictionary |
MethodChannel 示例代码
Flutter端代码:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class NativeCall{
static const _channelName = 'xyz.bczl/test';
// 创建通道,并设置名称作为唯一标识
static const _platform = const MethodChannel(_channelName);
static Future<void> sdkVersion() async {
try {
final int result = await _platform.invokeMethod('getSDKVersion');
debugPrint('sdkVersion=$result');
} on PlatformException catch (e) {
debugPrint("Failed to get sdkVersion: '${e.message}'.");
}
}
static Future<void> toast(String text) async {
try {
await _platform.invokeMethod('toast',{"text":text});
} on PlatformException catch (e) {
debugPrint(e.message);
}
}
}
Android端代码:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "xyz.bczl/test";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if(call.method.equals("getSDKVersion")){
// 返回SDK版本号
result.success(Build.VERSION.SDK_INT);
} else if(call.method.equals("toast")){
String text = call.argument("text");
// 弹出Toast
Toast.makeText(MainActivity.this,text,Toast.LENGTH_SHORT).show();
result.success(null);
}
}
});
}
}
EventChannel 示例代码
Flutter端,NativeCall
中添加如下代码
static const _eventChannel = const EventChannel("xyz.bczl/event");
StreamSubscription _subscription;
void onEvent(){
_subscription = _eventChannel
.receiveBroadcastStream()
.listen(
(event) {
debugPrint("from native event:$event");
},
onError: (e){
PlatformException exception = e;
debugPrint(exception.message);
});
}
void cancel(){
_subscription.cancel();
}
Android端代码:
public class MainActivity extends FlutterActivity {
EventChannel.EventSink mEvents;
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
// 创建 EventChannel
new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),"xyz.bczl/event")
.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
mEvents = events;
}
@Override
public void onCancel(Object arguments) {}
});
}
@Override
protected void onPause() {
super.onPause();
if (mEvents != null) mEvents.success("onPause");
}
@Override
protected void onResume() {
super.onResume();
if (mEvents != null) mEvents.success("onResume");
}
}
小结:
- 应在原生平台的主线程中调用通道相关的方法
- 编写调试原生混合代码是不能热更新的,请确保App重新编译、打包、安装
- Flutter 1.12 版本后官方更新了插件API,但是旧的接口目前依旧兼容。注意,新的版本中,是通过实现FlutterActivity的
configureFlutterEngine
方法创建通道,旧版处理如下:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "xyz.bczl/test";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {}
});
}
}
THE END