FlutterPlugin的探索

本文主要是介绍FlutterPlugin,涉及到原理和使用。

Flutter Plugin提供Android或者iOS的底层封装,在Flutter层提供组件功能,使Flutter可以较方便的调取Native的模块。很多平台相关性或者对于Flutter实现起来比较复杂的部分,都可以封装成Plugin。

那么flutter和native如何相互调用呢,原理如下


消息在client和host之间通过平台通道(platform channels)来进行的,之间的通讯都是异步的。

我们先介绍下MethodChannel的实现原理,使用方式以Android端为例:

//1、注册通道
    MethodChannel channel = new MethodChannel(getFlutterView(),"flutter/channel");

//2、设置回调,被call回调
    channel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
      @Override
      public void onMethodCall(MethodCall call, MethodChannel.Result result) {  
              //通知到flutter端
              result.success(“返回值”);
      }
    });
    
//3、主动call flutter的方法
    channel.invokeMethod("callFlutter", "params", new MethodChannel.Result() {
      @Override
      public void success(Object result) {
        //呼叫成功
      }

      @Override
      public void error(String errorCode, String errorMessage, Object errorDetails) {
        //呼叫出现异常
      }

      @Override
      public void notImplemented() {
        //flutter没有对应的实现方法
      }
    });

其实MethodChannel中的构造函数第一个参数就是BinaryMessenger,这个BinaryMessenger是在DartExecuter中初始化的,而BinaryMessenger的实现类中的send函数最终是对DartMessenger的一层包装,所以我们看消息是如何发送出去的,直接看DartMessengersend函数

  @Override
  public void send(
      @NonNull String channel,
      @Nullable ByteBuffer message,
      @Nullable BinaryMessenger.BinaryReply callback
  ) {
    Log.v(TAG, "Sending message with callback over channel '" + channel + "'");
    int replyId = 0;
    if (callback != null) {
      replyId = nextReplyId++;
      pendingReplies.put(replyId, callback);
    }
    if (message == null) {
      flutterJNI.dispatchEmptyPlatformMessage(channel, replyId);
    } else {
      flutterJNI.dispatchPlatformMessage(channel, message, message.position(), replyId);
    }
  }

如果有方法回调callback,就会生成一个replyId,然后把方法回调和replyId加入到一个map,如果没有就直接发送消息了。
如果消息体为空,就发送一个空消息,如果有消息内容,就把消息发送过去。还会携带一个replyId,这个会在回调的时候有用。发送消息是通过flutterJni分发方法,最终调到了c++层面,通过c++的dart虚拟机,把消息传递给了flutter。

如何收到flutter端的消息呢
同样的接受消息也是在DartExecutor,通过onAttachToJNI会建立通道关联,同样的消息会经过DartMessenger,如果是收到原生调用flutter以后的回复,会调用

  @Override
  public void handlePlatformMessageResponse(int replyId, @Nullable byte[] reply) {
    Log.v(TAG, "Received message reply from Dart.");
    BinaryMessenger.BinaryReply callback = pendingReplies.remove(replyId);
    if (callback != null) {
      try {
        Log.v(TAG, "Invoking registered callback for reply from Dart.");
        callback.reply(reply == null ? null : ByteBuffer.wrap(reply));
      } catch (Exception ex) {
        Log.e(TAG, "Uncaught exception in binary message reply handler", ex);
      }
    }
  }

首先根据replyId找到刚才发送消息时保存的callback,找到了,就把reply转化为bytebuff调用出去。BinaryReply会将消息回调回去。
如果是从flutter主动调动的消息稍微负责一些,也是类似的原理,只不过多了一步根据通道名字找到对象的处理类。

//三个参数,通道名字,消息的字节,从flutter端传递过来的replyId,
  public void handleMessageFromDart(
      @NonNull final String channel,
      @Nullable byte[] message,
      final int replyId
  ) {
    Log.v(TAG, "Received message from Dart over channel '" + channel + "'");
    
    //根据通道名字找到对象的处理类"
    BinaryMessenger.BinaryMessageHandler handler = messageHandlers.get(channel);
    if (handler != null) {
      try {
        Log.v(TAG, "Deferring to registered handler to process message.");
        
       //解码数据并调用onMessage传递消息 ,注意一下这个Reply
        final ByteBuffer buffer = (message == null ? null : ByteBuffer.wrap(message));
        handler.onMessage(buffer, new Reply(flutterJNI, replyId));
      } catch (Exception ex) {
        Log.e(TAG, "Uncaught exception in binary message listener", ex);
        //异常处理
        flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
      }
    } else {
      Log.v(TAG, "No registered handler for message. Responding to Dart with empty reply message.");
      //未实现通道处理
      flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
    }
  }

像Flutter官方提供的shared_preferences,就是通过通道来实现的。

FlutterPlugin还有另外一个用法,就是直接在Flutter端由Native渲染。比如视频播放插件video_player。
通常有两种做法,一种是PlatformView,另外一种是Texture(俗称外接纹理)。其中PlatformView区分Android和iOS,在Android平上上叫做 AndroidView,而在iOS平台,叫UIKitView。
前面提到的MethodChannel可以向flutter传输数据,但是如果将一个视频或者图片的数据传到flutter会很繁重,所以Flutter提供了一种基于Texture的数据共享机制,而以上两种方式原理都是基于Texture。

Texture https://api.flutter.dev/flutter/widgets/Texture-class.html

下图是视频插件的实现原理图


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,273评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,349评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,709评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,520评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,515评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,158评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,755评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,660评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,203评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,287评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,427评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,122评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,801评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,272评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,808评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,440评论 2 359

推荐阅读更多精彩内容

  • Flutter Plugin 资料 [TOC] 前言 在Flutter中,如果我们需要打印日志,如果不进行自定义,...
    zcwfeng阅读 5,398评论 3 3
  • 概述 调用原生功能 嵌入原有项目 Flutter模块调试 一、调用原生功能 1.1、Camera某些应用程序可能需...
    IIronMan阅读 1,117评论 1 7
  • 本文已授权「玉刚说」微信公众号独家发布 Flutter使用了一个灵活的系统,允许开发者调用特定平台的API,无论在...
    juexingzhe阅读 2,597评论 1 12
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,524评论 16 22
  • 创业是很多人的梦想,多少人为了理想和不甘选择了创业来实现自我价值,我就是其中一个。 创业后,我由女人变成了超人,什...
    亦宝宝阅读 1,816评论 4 1