Flutter App and Dart Message Communication Method
Flutter App Background: App Developer Vancouver
A lot of Flutter’s knowledge has been analyzed earlier in this series. In this article, let’s take a look at the relevant principles of Flutter platform communication. Flutter officially provides three platform and Dart message communication methods, they are MethodChannel, BasicMessageChannel, EventChannel, this article will continue the previous series to carry out an in-depth analysis of them, the source code depends on Flutter version 2.2.3, Platform chooses the familiar Android platform implementation.
The three official message communication methods of MethodChannel, BasicMessageChannel, and EventChannel are all full-duplex communication, so based on them, we can basically achieve various communication capabilities between Platform and Dart. Their respective applicable scenarios are as follows:
- MethodChanel: Used to transfer method calls, MethodCallHandler must eventually
result.success(x)return the result through the method on the UI thread, and before returning, you can asynchronously start a new thread to do any time-consuming operations.
- BasicMessageChannel: Used to transfer strings and semi-structured messages.
- EventChannel: Used for sending data stream.
Basic skills – Shopify Expert Vancouver
The basic usage of these communication methods will not be explained here. Here we will focus on the skills. There are two special points to pay attention to when writing Platform code:
- For Mac users, if you want to open the
.androidproject automatically created by Flutter through the Android Studio of the Mac , remember to use the shortcut key to
Command + Shift + '.'display the hidden directory after lifting the visitor .
- After modifying the code on the Platform side, if the operation does not take effect, please close the app and recompile, because hot deployment is invalid for the Platform.
In our daily work, we use MethodChannel the most, but it is not type-safe. In order to solve this problem, the official recommendation is to use the Pigeon package as a replacement for MethodChannel. It will generate code to send messages in a structured type-safe manner, but it is currently Not yet stable.
For more information about their basic use cases, please refer to the official document https://flutter.dev/docs/development/platform-integration/platform-channels
Source code analysis of message sending and receiving
In the source code analysis below, we still adhere to the way of use as the entry point, which is divided into Platform, Engine, and Dart layers.
The platform-side transceiver implementation process
Please remember the following picture before analyzing the Platform-side source code. The Java-side source code of the Platform below is analyzed based on this picture.
Let’s take a look at the source code of the members of MethodChannel, BasicMessageChannel and EventChannel on the Platform side respectively:
As you can see, no matter which method on the Platform side, they have three important members, namely:
- name String type. The unique identifier represents the name of the Channel. Because there are multiple Channels in a Flutter application, each Channel must be created with a unique name as the identifier. This has been seen in the previous series of source code analyses. Many frameworks implement their own name definitions.
- messager: BinaryMessenger type, acting as a messenger postman, a tool for sending and receiving messages.
- codec: MethodCodec or
MessageCodec<T>type, which acts as a codec for the message.
Flutter Engine C++ transceiver implementation process
The communication between the Platform and the Dart side above has been analyzed. Now the engine in the middle adhesive layer is called. The analysis of the Engine is still based on the calling sequence. Through the above analysis, we can get the following information:
- When calling Dart Java Platform eventually called FlutterJNI the
private native void nativeDispatchPlatformMessage(long nativeShellHolderId, String channel, ByteBuffer message, int position, int responseId)way to pass the Engine, Engine eventually called Dart Framework in
void _dispatchPlatformMessage(String name, ByteData? data, int responseId)method, and then passed to the layers of our Widget in MethodChannel.
- When Dart calls Platform, Dart finally calls the
String? _sendPlatformMessage(String name, PlatformMessageResponseCallback? callback, ByteData? data)method of PlatformDispatcher (that is
native 'PlatformConfiguration_sendPlatformMessage') to the Engine, and Engine finally calls the
public void handlePlatformMessage(final String channel, byte message, final int replyId)method of FlutterJNI on the Platform side , which is then passed layer by layer to the onMethodCall method of the MethodCallHandler callback set by our MethodChannel.