之前讲过一篇Flutter与原生通信,为大家讲解了Flutter如何调用原生,但是没有介绍原生如何调用Flutter,那么原生如何调用Flutter呢?
诶~,还是通过MethodChannel,只不过这次它俩角色互换了一下,之前是原生作为通信方法的提供方,Flutter为调用方,现在倒过来了,Flutter作为通信方法的提供方,原生作为调用方。是不是很有意思。
Flutter端(提供方)
和在原生中一样,通过MethodChannel的setMethodCallHandler方法进行注册,提供原生调用的通信方法。需要实现一个参数为MethodCall,返回值为Future对象的函数。
void setMethodCallHandler(Future<dynamic> Function(MethodCall call)? handler) {
_methodChannelHandlers[this] = handler;
binaryMessenger.setMessageHandler(
name,
handler == null
? null
: (ByteData? message) => _handleAsMethodCall(message, handler),
);
}
MethodCall
MethodCall应该不陌生吧,在上一篇博客了我们见过它了,但是Flutter中的MethodCall和原生中的MethodCall还有点不一样,Flutter中的MethodCall只有属性,没有方法。
/// 表示调用命名方法的命令对象。
@immutable
class MethodCall {
/// 创建一个 [MethodCall],表示使用指定的 [arguments] 调用 [method]。
const MethodCall(this.method, [this.arguments])
: assert(method != null);
/// 要调用的方法的名称。
final String method;
/// 方法的参数。
///
/// 必须是使用的 [MethodCodec] 的有效值。
///
/// 这个属性是动态的,这意味着访问时会跳过类型检查
/// 这个性质。 为了最大限度地降低运行时类型错误的风险,该值应该访问时被强制转换为`Object?`。
final dynamic arguments;
@override
String toString() => '${objectRuntimeType(this, 'MethodCall')}($method, $arguments)';
}
我们在flutter中注册一个’lal‘方法,将原生传递过来的参数编成一段话返回给原生。
static const nativeChannel =
const MethodChannel("com.fengwo.reading.flutter_app/native");
//对方法进行注册
nativeChannel.setMethodCallHandler((call) {
if(call.method == "lal") {
return Future.value("Hello~ ${call.arguments}\nI'm flutter");
}
return null;
});
原生端(调用方)
原生中调用flutter,同样通过MethodChannel的invokeMethod方法,其有三个参数,第一个是flutter中定义的方法名称,第二个是要传递的参数,第三个是调用flutter方法结果的回调接口。
@UiThread
public void invokeMethod(String method, @Nullable Object arguments, @Nullable Result callback) {
messenger.send(
name,
codec.encodeMethodCall(new MethodCall(method, arguments)),
callback == null ? null : new IncomingResultHandler(callback));
}
现在,我们使用原生调用flutter中的'lal'方法,传递参数字符串‘android’,将flutter返回的结果通过toast打印出来。
class SecondActivity : FlutterActivity() {
lateinit var channel: MethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NATIVE)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
btn.setOnClickListener {
channel.invokeMethod("lal", "android", object : MethodChannel.Result {
override fun notImplemented() {
Toast.makeText(this@SecondActivity, "notImplemented", Toast.LENGTH_SHORT).show()
}
override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
Toast.makeText(this@SecondActivity, "error:$errorMessage", Toast.LENGTH_SHORT).show()
}
override fun success(result: Any?) {
if (result != null)
Toast.makeText(this@SecondActivity, result as String, Toast.LENGTH_SHORT).show()
}
})
}
}
}
演示