原生与Flutter通信

Posted Ever69

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生与Flutter通信相关的知识,希望对你有一定的参考价值。

 

之前讲过一篇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只有属性,没有方法。

MethodCodec支持的有效值看这里

/// 表示调用命名方法的命令对象。
@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()
                }

            })
        }
    }
}

演示

 

 

以上是关于原生与Flutter通信的主要内容,如果未能解决你的问题,请参考以下文章

Flutter与原生通信概述

原生与Flutter通信

原生与Flutter通信

原生与Flutter通信

MethodChannel 实现flutter 与 原生通信

Flutter通过MethodChannel实现Flutter 与Android iOS 的双向通信