当前位置:网站首页>Methodchannel of flutter
Methodchannel of flutter
2022-06-25 09:51:00 【sunny_ yin8899】
Preface
Flutter yes Google Use Dart Language development of a set of mobile application development framework . It is different from other development frameworks :
because Flutter Use AOT Precompiled code is machine code , So it runs more efficiently .
Flutter Of UI Control does not use the underlying native control , But use Skia Rendered by rendering engine , Because it doesn't depend on the underlying controls , So the multi terminal consistency is very good .
Flutter The scalability of the system is also very strong , Developers can use Plugin And Native communicate .
brief introduction
Flutter Using a flexible system , Allows you to invoke platform specific API, No matter in Android Upper Java or Kotlin In the code , still iOS Upper ObjectiveC or Swift Available in code .
Flutter Platform specific API Support does not depend on code generation , It relies on flexible messaging :
Applied Flutter Partly through the platform channel (platform channel) Send the message to the host of its application (iOS or Android).
The platform channel the host is listening to , And receive the message . It then calls the platform specific API( Using native programming languages ) - And send the response back to the client , That is, the application's Flutter part .
The framework outlined : Platform channel
Use the platform channel on the client (Flutter UI) And hosts ( platform ) Passing messages between , As shown in the figure below :)]
Messages and responses are delivered asynchronously , To ensure that the user interface remains responsive ( It won't hang ).
On the client side ,MethodChannel (API) You can send messages corresponding to method calls . On the host platform ,MethodChannel stay Android((API) and FlutterMethodChannel iOS (API) You can receive method calls and return results . These classes allow you to use very little “ The scaffold ” Code development platform plug-ins .
Platform channel data type support and decoder
Standard platform channels use standard message codecs , To support simple things like JSON Efficient binary serialization of values , for example booleans,numbers, Strings, byte buffers, List, Maps( see also StandardMessageCodec Learn more ). When you send and receive values , The serialization and deserialization of these values in the message are automatic .
Flutter Three different types of Channel, They are
- BasicMessageChannel: Used to pass strings and semi-structured information .
- MethodChannel: Used to pass method calls (method invocation).
- EventChannel: For data flow (event streams) Communication for .
BasicMessageChannel Androd End :
BasicMessageChannel Flutter End :
EventChannel Androd End :
EventChannel Flutter End :
Three Channel Independent of each other , Have different purposes , But they are very similar in design . Each of these Channel There are three important member variables :
- name: String type , representative Channel Name , It is also its unique identifier .
- messager:BinaryMessenger type , On behalf of the messenger , It is a tool for sending and receiving messages .
- codec: MessageCodec Type or MethodCodec type , Represents the codec of the message .
Channel name
One Flutter There may be multiple in the application Channel, Every Channel A unique... Must be specified when creating name,Channel Used between name To distinguish each other . When there is news from Flutter End sent to Platform End time , It will be passed on according to it channel name To find the Channel Corresponding Handler( Message handler )
BinaryMessenger yes Platform End and Flutter Tools for end-to-end communication , The message format used for communication is binary format data . When we initialize a Channel, And to the Channel Register to process messages Handler when , In fact, a corresponding BinaryMessageHandler, And channel name by key, Sign up to BinaryMessenger in . When Flutter Send message to BinaryMessenger when ,BinaryMessenger According to its input channel Find the corresponding BinaryMessageHandler, And let them deal with it .
Binarymessenger stay Android The end is an interface , Its concrete realization is FlutterNativeView.
private final Map<String, BinaryMessageHandler> mMessageHandlers;
...
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
if(handler == null) {
this.mMessageHandlers.remove(channel);
} else {
this.mMessageHandlers.put(channel, handler);
}
}
Binarymessenger Don't know Channel The existence of , It's only with BinaryMessageHandler Dealing with . and Channel and BinaryMessageHandler Is a one-to-one correspondence . because Channel from BinaryMessageHandler The received message is in binary format , Cannot be used directly , so Channel The binary message will be passed through Codec( Message codec ) Decode into a recognizable message and deliver it to Handler To deal with .
When Handler After processing the message , It will return... Through the callback function result, And will result It is encoded into binary format data by codec , adopt BinaryMessenger Send back Flutter End .
private void handlePlatformMessage(final String channel, byte[] message, final int replyId) {
this.assertAttached();
BinaryMessageHandler handler = (BinaryMessageHandler)this.mMessageHandlers.get(channel);
...
if(reply == null) {
FlutterNativeView.nativeInvokePlatformMessageEmptyResponseCallbac (FlutterNativeView.this.mNativePlatformView, replyId);
} else {
FlutterNativeView.nativeInvokePlatformMessageResponseCallback (FlutterNativeView.this.mNativePlatformView, replyId, reply, reply.position());
}
...
}
Message codec :Codec
Message codec Codec It is mainly used to convert binary format data into Handler Identifiable data ,Flutter It defines two kinds of Codec:MessageCodec and MethodCodec.
MessageCodec
It's an interface , Two methods are defined :encodeMessage Receive a specific data type T, And encode it into binary data ByteBuffer, and decodeMessage Receive binary data ByteBuffer, Decode it into a specific data type T.
MessageCodec There are many different implementations :
- BinaryCodec
- StringCodec
- JSONMessageCodec
- StandardMessageCodec
MethodCodec
MethodCodec For binary data and method calls (MethodCall) Codec between and the returned result .MethodChannel and EventChannel The codecs used are MethodCodec.
And MessageCodec The difference is ,MethodCodec be used for MethodCall Object encoding and decoding , One MethodCall Object represents a time from Flutter End initiated method calls .MethodCall Yes 2 Member variables :String Type of method Represents the name of the method to be called , Generic type (Android In Chinese, it means Object,iOS In Chinese, it means id) Of arguments Represents the method to be called .
Because it deals with method calls , So compared to MessageCodec,MethodCodec More processing of the call results . When the method call succeeds , Use encodeSuccessEnvelope take result Encoded as binary data , And when the method call fails , Then use encodeErrorEnvelope take error Of code、message、detail Encoded as binary data
MethodCodec There are two realizations :
- JSONMethodCodec
- StandardMethodCodec
Message handler :Handler
When we receive binary format messages and use Codec Decode it to Handler After the message that can be processed , We should Handler Come on. .Flutter Three types of Handler, And Channel The types correspond one by one . We ask Channel Sign up for a Handler when , In fact, it is to BinaryMessager Register a corresponding BinaryMessageHandler. When news is sent to BinaryMessageHandler after ,Channel Will pass Codec Decode the message , And pass it on to Handler Handle .
MessageHandler
MessageHandler Users process strings or semi-structured messages , Its onMessage Method to receive a T Type of message , And asynchronously return the same type result.MessageHandler The function of is quite basic , Less use scenarios , But its cooperation BinaryCodec When using , It can easily transfer binary data messages .
MethodHandler
MethodHandler For handling method calls , Its onMessage Method to receive a MethodCall Type message , And according to MethodCall Member variables of method To call the corresponding API, When it's done , Depending on whether the method call succeeds or fails , Return the corresponding result .
StreamHandler
StreamHandler Slightly different from the first two , Communication for event flow , The most common use is Platform To the end Flutter Send event messages on the client . When we achieve one StreamHandler when , Need to implement its onListen and onCancel Method . And in the onListen Methods in the reference , There is one EventSink( Its presence Android It's an object ). We hold EventSink after , You can pass EventSink towards Flutter Send event messages on the client .
Understand the message encoding and decoding process
Flutter Official documents say ,standard platform channels Use standard messsage codec Yes message and response Serialization and deserialization ,message And response It can be booleans, numbers, Strings, byte buffers,List, Maps wait , The serialized data is in binary format .
So in the example mentioned above ,java.lang.Integer The return value of type is first serialized into a piece of data in binary format , The data is then passed to flutter Lateral posterior , Is deserialized to dart In language int Data of type .
When message or response Need to be encoded as binary data , Would call StandardMessageCodec Of writeValue Method , This method receives a file named value Parameters of , And according to its type , To the binary data container (ByteArrayOutputStream) Write the... Corresponding to this type type value , And then convert the data into binary representation , And write to the binary data container .
and message perhaps response When it needs to be decoded , It uses StandardMessageCodec Of readValue Method , The method receives binary format data , Will first read a byte Indicates its type, And according to it type Convert binary data to corresponding data type .
for example 100, When this value is converted to binary data , Will first write to the binary data container int The type corresponds to type value :3, Then write the charge value 100 Converted 4 individual byte. And when Flutter When the end receives the binary data , First read the first byte value , And according to its value, the data is int type , next , Read the following 4 individual byte, And turn it into dart Type of int.
Understand the messaging process
The following is an example to understand the message passing process .
The messaging : from Flutter To Platform
Interaction diagram
Flutter End
We are Flutter End use MethodChannel Of invokeMethod Method initiates a method call ,invokeMethod Method will put it into the parameter message and arguments Encapsulate into a MethodCall object , And use MethodCodec Encode it into binary format data , Re pass BinaryMessages Send a message
Future<String> getString(String key,String value) async {
String result;
try {
final Map<String, dynamic> params = <String, dynamic>{
'key': '$key',
};
params['value'] = value;
result = await _sChannel
.invokeMethod('getString', params);
} on PlatformException catch (e) {
print(e.toString());
}
return result;
}
call methodchannel obtain getString Value . Let's follow the code execution process in turn .invokeMethod The method is executed as follows :
Future<dynamic> invokeMethod(String method, [dynamic arguments]) async {
assert(method != null);
final dynamic result = await BinaryMessages.send(
name,
codec.encodeMethodCall(new MethodCall(method, arguments)),
);
if (result == null)
throw new MissingPluginException('No implementation found for method $method on channel $name');
return codec.decodeEnvelope(result);
}
Finally, it will be implemented to :
void sendPlatformMessage(String name,
ByteData data,
PlatformMessageResponseCallback callback) {
final String error =
_sendPlatformMessage(name, _zonedPlatformMessageResponseCallback(callback), data);
if (error != null)
throw new Exception(error);
}
String _sendPlatformMessage(String name,
PlatformMessageResponseCallback callback,
ByteData data) native 'Window_sendPlatformMessage';
The native method is called here , Again flutter engine Source code window.cc You can find :
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_defaultRouteName", DefaultRouteName, 1, true},
{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
{"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
{"Window_render", Render, 2, true},
{"Window_updateSemantics", UpdateSemantics, 2, true},
{"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
});
}
_SendPlatformMessage Function corresponds to :
void _SendPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&SendPlatformMessage, args);
}
Called to SendPlatformMessage:
Dart_Handle SendPlatformMessage(Dart_Handle window,
const std::string& name,
Dart_Handle callback,
const tonic::DartByteData& data) {
UIDartState* dart_state = UIDartState::Current();
if (!dart_state->window()) {
// Must release the TypedData buffer before allocating other Dart objects.
data.Release();
return ToDart("Platform messages can only be sent from the main isolate");
}
fml::RefPtr<PlatformMessageResponse> response;
if (!Dart_IsNull(callback)) {
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback),
dart_state->GetTaskRunners().GetUITaskRunner());
}
if (Dart_IsNull(data.dart_handle())) {
dart_state->window()->client()->HandlePlatformMessage(
fml::MakeRefCounted<PlatformMessage>(name, response));
} else {
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
dart_state->window()->client()->HandlePlatformMessage(
fml::MakeRefCounted<PlatformMessage>(
name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
response));
}
return Dart_Null();
}
go through , Here comes the key part dart_state->window()->client()->HandlePlatformMessage(…);
Again WindowClient Find this function in .
class WindowClient {
public:
virtual std::string DefaultRouteName() = 0;
virtual void ScheduleFrame() = 0;
virtual void Render(Scene* scene) = 0;
virtual void UpdateSemantics(SemanticsUpdate* update) = 0;
virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) = 0;
virtual FontCollection& GetFontCollection() = 0;
virtual void UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) = 0;
protected:
virtual ~WindowClient();
};
It's a pure virtual function , Find the implementation class RuntimeController, You can find RuntimeDelegate& client_, Then follow the trend to find engine.h Inherited RuntimeDelegate.
class Delegate {
public:
virtual void OnEngineUpdateSemantics(
blink::SemanticsNodeUpdates update,
blink::CustomAccessibilityActionUpdates actions) = 0;
virtual void OnEngineHandlePlatformMessage(
fml::RefPtr<blink::PlatformMessage> message) = 0;
virtual void OnPreEngineRestart() = 0;
virtual void UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) = 0;
};
among OnEngineHandlePlatformMessage It's about HandlePlatformMessage Call to , So find Delegate Where this class is called, you can find HandlePlatformMessage Call to . The global search is finalized PlatformViewAndroid There are calls to Delegate
PlatformViewAndroid(PlatformView::Delegate& delegate,
blink::TaskRunners task_runners,
fml::jni::JavaObjectWeakGlobalRef java_object);
In the end in platform_view_android.cc The call :
// |shell::PlatformView|
void PlatformViewAndroid::HandlePlatformMessage(
fml::RefPtr<blink::PlatformMessage> message) {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> view = java_object_.get(env);
if (view.is_null())
return;
int response_id = 0;
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
auto java_channel = fml::jni::StringToJavaString(env, message->channel());
if (message->hasData()) {
fml::jni::ScopedJavaLocalRef<jbyteArray> message_array(
env, env->NewByteArray(message->data().size()));
env->SetByteArrayRegion(
message_array.obj(), 0, message->data().size(),
reinterpret_cast<const jbyte*>(message->data().data()));
message = nullptr;
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),
message_array.obj(), response_id);
} else {
message = nullptr;
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),
nullptr, response_id);
}
}
Again platform_view_android_jni.cc Find :
void FlutterViewHandlePlatformMessage(JNIEnv* env,
jobject obj,
jstring channel,
jobject message,
jint responseId) {
env->CallVoidMethod(obj, g_handle_platform_message_method, channel, message,
responseId);
FML_CHECK(CheckException(env));
}
Finally find :
g_flutter_native_view_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/view/FlutterNativeView"));
if (g_flutter_native_view_class->is_null()) {
return false;
}
FlutterNativeView It's our java Code. . Here we can come to an end . The corresponding is :
In the following calls, we can trace the code all the way to understand .
Reference material
https://www.jianshu.com/p/39575a90e820
https://www.colabug.com/3916347.html
https://www.jianshu.com/p/cb96d62f5042
https://flutter.io/platform-channels/
边栏推荐
- 处理图片类库
- Oracle function trigger
- Arduino bootloader burning summary
- Lvs-dr mode single network segment case
- Is it harder to find a job in 2020? Do a good job in these four aspects and find a good job with high salary
- Vscode attempted to write the procedure to a pipeline that does not exist
- 2022 meisai question a idea sharing
- Is it safe to open an account on the compass?
- 在指南针上面开户好不好,安不安全?
- JS tool function, self encapsulating a throttling function
猜你喜欢
Remove the mosaic, there's a way, attached with the running tutorial
Wallys/MULTI-FUNCTION IPQ6010 (IPQ6018 FAMILY) EMBEDDED BOARD WITH ON-BOARD WIFI DUAL BAND DUAL
[learn C from me and master the key to programming] insertion sort of eight sorts
Learning notes of rxjs takeuntil operator
Reza RA series - development environment construction
Pytorch_ Geometric (pyg) uses dataloader to report an error runtimeerror: sizes of tenants must match except in dimension 0
[zufe school competition] difficulty classification and competition suggestions of common competitions in the school (taking Zhejiang University of Finance and economics as an example)
[wechat applet full stack development course] course directory (mpvue+koa2+mysql)
2022 postgraduate entrance examination experience post -- Alibaba Business School of Hangzhou Normal University -- management science and Engineering (including the recommendation of books and course
[2020 cloud development + source code] 30 minutes to create and launch wechat applet practical project | zero cost | cloud database | cloud function
随机推荐
Creating a binary tree (binary linked list) from a generalized table
Use evo
Data-driven anomaly detection and early warning of item C in the May 1st mathematical modeling competition in 2021
Remittance international empowers cross-border e-commerce: to be a compliant cross-border payment platform!
manhattan_ Slam environment configuration
The problem of automatic page refresh after the flyer WebView pops up the soft keyboard
What should be paid attention to in PMP examination?
Neo4jdesktop (neo4j desktop version) configures auto start (boot auto start)
Study on correlation of pumpkin price and design of price prediction model based on BP neural network
Flutter replaces the default icon of Gaud positioning
SQL高级
With the QQ group file storage function of super nice, you immediately have n cloud disks that are easy to download and never expire
Is it safe for Huatai Securities to open an account on it? Is it reliable?
Is it safe to open a stock account on the compass?
从海量手机号中匹配某一个手机号
Is it safe to open an account on the compass?
[wechat applet full stack development course] course directory (mpvue+koa2+mysql)
Neat Syntax Design of an ETL Language (Part 2)
Is it safe to open an account in a mobile phone or a securities company?
[buuctf.reverse] 117-120