80

Flutter Platform Channel 使用与源码分析

 4 years ago
source link: https://www.tuicool.com/articles/vaEJ3i2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

奇技指南

本文是Flutter系列第三篇文章,将为大家介绍Flutter与Native通信使用及原理分析。

本文来自公众号 奇舞移动技术

01

为什么要有 PlatformChannel

1、如果 Flutter 要获取设备的电量信息怎么办?

2、如果 Flutter 要实时监控网络状态怎么办?

由于 Flutter 特点如下:

Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.

1、Flutter 是一个跨平台的 UI 库,专注于构建高效的 UI。

2、多平台的支持,下图是 Flutter 目前支持的平台,每个平台的都有自己的平台特性。

fUf6Zba.jpg!web

基于以上两点,目前 Flutter 如果要和平台相关的部分通信需要有一个通道即 PlatformChannel。

02

架构图

3YNbAzr.png!web

03

PlatformChannel 类型

  • BasicMessageChannel:用于数据传递。platform 和 dart 可互相传递数据(asynchronous message passing)

  • MethodChannel:用于传递方法调用。platform 和 dart 可互相调用方法(asynchronous method calls)

  • EventChannel:用于数据流通信。建立连接之后,platform 发送消息,dart 接收消息(event streams)

三种类型的 channel 都定义在 platform_channel.dart 中,从源码中可以看到三种 channel 都用到了以下三个属性。

  • name :String 类型,表示 channel 的名字,全局唯一(The logical channel on which communication happens)

  • codec :MessageCodec  类型,消息的编码解码器(The message codec used by this channel)

  • binaryMessenger :BinaryMessenger类型,用于发送数据(The messenger used by this channel to send platform messages)

3.1 channel name

channel 的名字,每个 Flutter 应用可能有多个 channel,但是每个 channel 必须有一个唯一的名字。

3.2 codec

codec 用来对数据编码解码,以便两端可以正确读取数据。 AZJv2ya.jpg!web

3.3 b inaryMessenger

用于发送数据

04

PlatformChannel 使用

4.1 MethodChannel

Dart 调用 Android 方法

methodchannelpage.dart 主要代码

MainActivity.java 主要代码

从以上代码可以看出Dart 调用 Android 代码分三步。首先在 Dart 端定义 MethodChannel 名字为 method_channel_sample。然后定义 getUserInfo方法,传入要调用的方法名和参数。最后点击按钮执行方法,获取用户信息。

在 Android 端定一个 MethodChannel 名字和 Dart 端保持一致。设置 MethodCallHandler。当调用的是 getInfo方法时,根据参数返回信息。

Android 调用 Dart 方法

MainActivity.java 主要代码

methodchannelpage.dart 主要代码

从代码可以看出,在 Dart 端设置 MethodCallHandler 然后在 Android 端调用即可。

4.2 BasicMessageChannel

Dart 向 Android 发送消息

basicmessagechannel_page.dart 主要代码

MainActivity.java 主要代码

从以上代码可以看出:

Dart 向 Android 发送消息依然分为三步。首先在 Dart 端定义 BasicMessageChannel 名字为 basic_message_channel_sample。然后定义发送消息的方法 sayHelloToNative。最后点击按钮向 Android 端发送消息。

在 Android 端定一个 BasicMessageChannel 名字和 Dart 端保持一致。设置 MethodCallHandler。当收到消息时发一个回复。

Android 向 Dart 发送消息

MainActivity.java 主要代码

basicmessagechannel_page.dart 主要代码

从代码可以看出,在 Dart 端设置 MessageHandler 然后在 Android 端直接发送消息即可。

4.3 EventChannel

eventchannelpage.dart 主要代码

MainActivity.java 主要代码

Dart 接受 Android stream event。首先在 Dart 端定义 EventChannel 名字为 event_channel_sample。然后设置 receiveBroadcastStream 监听,当 Android 端有消息发过来会回调 _onEvent 方法。

在 Android 端启动一个定时器,每隔 3s 向 Dart 端发送一次消息。

4.4 总结

如下图,在 Dart 与 Platform 通信过程中,通过 channel name 找到对方,然后把消息通过 codec 进行编解码,最后通过 binaryMessenger 进行发送。 MfQNzaY.png!web

05

源码分析

5.1

调用 MethodChannel 的 invokeMethod 方法,会调用到 binaryMessenger.send 方法。即 binaryMessenger.send 传入 channel name 和编码好的参数

5.2

binary_messenger.dart 的 send 方法会调用当前对象的 _sendPlatformMessage 方法,最终会调用 window.sendPlatformMessage 方法

5.3

在 window.dart 中又调用了 native 方法 _sendPlatformMessage

5.4

接下来进入 engine 中的 window.cc,可以看到最终调用的是 dart_state->window()->client()->HandlePlatformMessage

window.cc 源码
https://github.com/flutter/engine/blob/master/lib/ui/window/window.cc

5.5

我们进入 window.h 中找到 client 其实是 WindowClient

window.h 源码
https://github.com/flutter/engine/blob/master/lib/ui/window/window.h

5.6

在 runtime_controller.h 中可以看到 RuntimeController 是 WindowClient 的实际实现,调用的是 RuntimeController 的 HandlePlatformMessage 方法

runtime_controller.h 源码
https://github.com/flutter/engine/blob/78a8ca0f62b04fa49030ecdd2d91726c0639401f/runtime/runtime_controller.h

5.7

在 runtimecontroller.cc 中,HandlePlatformMessage 调用了 client 的 HandlePlatformMessage 方法,client_ 实际是代理对象 RuntimeDelegate

runtime_controller.cc 源码
https://github.com/flutter/engine/blob/78a8ca0f62b04fa49030ecdd2d91726c0639401f/runtime/runtime_controller.cc

5.8

engine. 是 RuntimeDelegate 的具体实现类

engine.h 源码
https://github.com/flutter/engine/blob/78a8ca0f62b04fa49030ecdd2d91726c0639401f/shell/common/engine.h

5.9

engine.cc 中调用了 delegate_ 的 OnEngineHandlePlatformMessage 方法

engine.cc 源码
https://github.com/flutter/engine/blob/78a8ca0f62b04fa49030ecdd2d91726c0639401f/shell/common/engine.cc

5.10   shell.h 是 Engine 的代理

shell.h 源码
https://github.com/flutter/engine/blob/ed8e35c4cfe12f836133944c968e00ca52593d43/shell/common/shell.h

5.11

调用流程又进入了 shell.cc 的 HandleEngineSkiaMessage 方法,把消费放到 TaskRunner 中

shell.cc 源码
https://github.com/flutter/engine/blob/ed8e35c4cfe12f836133944c968e00ca52593d43/shell/common/shell.cc

5.12

当 task 执行是会调用 platformviewandroid.h 的 HandlePlatformMessage 方法

platformviewandroid.h 源码
https://github.com/flutter/engine/blob/56052c70afcbdff2d39d2af279fcc52666122dbf/shell/platform/android/platform_view_android.h

5.13

在 platformviewandroid.cc 的 HandlePlatformMessage 中,开始通过 jni 调用 java 端的方法,java_channel 即要找的 channel

platform view android.cc 源码 https://github.com/flutter/engine/blob/56052c70afcbdff2d39d2af279fcc52666122dbf/shell/platform/android/platform_view_android.cc

5.14

在 platformviewandroidjni.cc 中可以看到 ghandleplatformmessage_method 就是 FindClass("io/flutter/embedding/engine/FlutterJNI") 类的 handlePlatformMessage 方法。至此 engine 代码执行结束

engine 代码执行结束。

platformviewandroid_jni.cc 源码
https://github.com/flutter/engine/blob/ed8e35c4cfe12f836133944c968e00ca52593d43/shell/platform/android/platform_view_android_jni.cc

5.15

在 FlutterJNI 中调用了 this.platformMessageHandler.handleMessageFromDart 方法。也就是 DartMessenger 的 handleMessageFromDart 方法

5.16

DartMessenger 中 messageHandlers 通过 channel 名找到对应的 handler 进行处理,这个 handler 就是我们在 java 代码里通过 channel 设置的,整个调用流程完成

Demo 地址

https://github.com/roc-x/roc-samples/tree/master/flutter_platform_channel

参考资源

https://flutter.dev/docs/development/platform-integration/platform-channels

https://github.com/flutter/flutter/tree/master/examples/platform_channel

https://www.yuque.com/xytech/flutter/fu7h25

相关推荐

更多移动端知识,就在奇舞移动技术

yUbUzu6.jpg!web

界世的你当不

只做你的肩膀

qMFR7jj.jpg!web

fMzuInB.jpg!web

360官方技术公众号 

技术干货|一手资讯|精彩活动

空·

EzAV7v2.gif

点击“阅读原文”查看Demo

右边给我一朵小花花

EzAV7v2.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK