聊聊Flutter Platform SDK

[TOC]

前言

? 從Flutter的架構(gòu)圖中可以看出,F(xiàn)lutter Platform SDK處于整個Flutter框架的上層,連接了Java與Dart代碼。那么作為“最上層”的它,到底扮演了哪些角色,以及是如何扮演好這些角色的呢?Google工程師用一個封裝好的flutter.jar包"show me the answer"。

Platform SDK 的角色扮演

? 通過對Platform SDK(以下簡稱 Platform)源碼的閱讀,可以大致將它分成三個角色:Creator(創(chuàng)建者),Transmitter(傳遞者),Registrant(注冊人)。

Creator

創(chuàng)建者

FlutterMain
時序圖
flutter_seq.png

FlutterMain擔(dān)任著flutter的初始化工作,在被Application的onCreate調(diào)起后

  • initConfig

    必須的配置文件名稱和路徑

    • 通過命令行 flutter build aot生成的文件

      名稱 內(nèi)容
      isolate_snapshot_instr 應(yīng)用程序指令段
      isolate_snapshot_data 應(yīng)用程序數(shù)據(jù)段
      vm_snapshot_instr VM 虛擬機(jī)指令段
      vm_snapshot_data VM 虛擬機(jī)數(shù)據(jù)段

    ? 注:詳細(xì)含義參見官方說明

    • 路徑信息

      flutter_assets等文件的路徑信息

  • initAot

    1. 初始化標(biāo)記位:snapshot文件集成的方式。
    2. sIsPrecompiledAsSharedLibrary 代表的是把所有的snapshot文件打包成一個動態(tài)庫(一種類似ios的集成方式)。
    3. 禁止同時采用兩種集成方式。
  • initResource

    1. 創(chuàng)建了一個ResourceExtractor 對象,他是Resource文件的搬運(yùn)工
    2. 通過ResourceExtractor 對象的addResource方法初始化需要搬運(yùn)的文件
    3. ResourceExtractor啟動異步任務(wù)把a(bǔ)sset下面的文件搬運(yùn)到DataDir的flutter目錄下面

FlutterActivityDelegate

WhatDelegate
//FlutterActivity.java
......
private final FlutterActivityEvents eventDelegate;
private final Provider viewProvider;
private final PluginRegistry pluginRegistry;   
private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
......
public FlutterActivity() {
        this.eventDelegate = this.delegate;
        this.viewProvider = this.delegate;
        this.pluginRegistry = this.delegate;
    }
......

我們可以從上面FlutterActivity的構(gòu)造函數(shù)中看出Delegate到底代理了哪些職責(zé)

  • FlutterActivityEvents:將Activity生命周期的具體處理邏輯傳遞給FlutterView

  • Provider:在onCreate中創(chuàng)建的FlutterView,通過實(shí)現(xiàn)Provider的接口暴露出來

  • PluginRegistry:插件信息的注冊與查詢傳遞給FlutterView

    從上面看來,其實(shí)FlutterActivityDelegate直接交互的對象就是FlutterView,通過這樣的設(shè)計(jì),提高了每一個類的內(nèi)聚性

flutter內(nèi)聚.png

FlutterView

可以先簡單的把FlutterView看成是負(fù)責(zé)顯示的,而把后面的FlutterNativeView看成是負(fù)責(zé)通信的。

  • 解偶系統(tǒng)控件

    首先我們可以看到FlutterView是繼承自SurfaceView的,提到SurfaceView我們肯定會想到“挖洞”,“雙緩沖”這些詞,也正是因?yàn)檫@些特性FlutterView可以很好的把UI渲染工作交給Flutter( 后者通過dart->組裝LayerTree->Skia完成繪制 )。

1655b109f83bea9b.png
  • 傳遞狀態(tài)消息給Dart UI

    這些消息大致可以將它們分成七個模塊,兩大類

    1. 通過反射原生系統(tǒng)的api進(jìn)行數(shù)據(jù)通訊

      多語言模塊、系統(tǒng)信息和用戶設(shè)置

    2. 將數(shù)據(jù)打包成特殊格式以消息的形式和使用Dart編寫的flutter控件交互

      生命周期、按鍵消息、路由導(dǎo)航和平臺插件

FlutterNativeView

可以先簡單的把FlutterNativeView看成是負(fù)責(zé)通信的。它在系統(tǒng)層面上實(shí)現(xiàn)了BinaryMessenger接口 [這在下文Transmitter中詳細(xì)介紹]。

Transmitter

傳遞者

消息渠道

  • Flutter針對不同的應(yīng)用場景封裝了3類Channel

    1. MethodChannel:調(diào)用方法
    2. BasicMessageChannel:自定義結(jié)構(gòu)信息
    3. EventChannel:事件的通知
  • 3類Channel擁有相似的結(jié)構(gòu)類型

    1. 信使BinaryMessenger:我們自己創(chuàng)建的channel一般就是FlutterNativeView
    2. channel 名:channel的key值,不可重復(fù)
    3. MethodCodec /MessageCodec 解碼器: 針對不同的channle解碼二進(jìn)制應(yīng)答數(shù)據(jù)
channel.png

消息編解碼

? 標(biāo)準(zhǔn)平臺通道使用一個標(biāo)準(zhǔn)的消息編解碼器。簡單的JSON類值(如布爾值)的高效二進(jìn)制序列化,數(shù)字、字符串、字節(jié)緩沖區(qū)以及這些列表和映射。(查看細(xì)節(jié) StandardMessageCodec)。這些值的序列化和反序列化在消息發(fā)送和接收值時自動發(fā)生。(對應(yīng)的數(shù)據(jù)轉(zhuǎn)化關(guān)系如下)

解碼.jpg

傳遞流程

? 通過Flutter Engine的數(shù)據(jù)轉(zhuǎn)換,使得Dart和Android之間可以進(jìn)行通信

channel流程圖.png

Registrant

注冊人

情境轉(zhuǎn)換

? 首先這里有三個形似得英文單詞registry, registrar and registrant分別對應(yīng)注冊局,注冊商和注冊人。把它們翻譯到現(xiàn)實(shí)的生活場景中的角色其實(shí)是一個“注冊人通過注冊商,更新注冊信息后,注冊商把信息傳遞給注冊局進(jìn)行保存”的過程。下面我們把這個過程再翻譯回代碼:

首先我們新建一個plugin插件,作為說明的對象:

// 實(shí)現(xiàn) PluginRegistry.ActivityResultListener
public class FlutterMusicPlugin implements MethodCallHandler, PluginRegistry.ActivityResultListener {
    ...
    public static void registerWith(Registrar registrar) {
        //傳入Activity
        final FlutterMusicPlugin plugin = new FlutterMusicPlugin(registrar.activity());
        ...
        // 注冊ActivityResult回調(diào)
        registrar.addActivityResultListener(plugin);
    }
    
    @Override
    public void onMethodCall(MethodCall call, Result result) {
           ...
    }
    
    @Override
    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
           ...
        return false;
    }
}

同時在GeneratedPluginRegistrant類中會自動生成

public final class GeneratedPluginRegistrant {
  public static void registerWith(PluginRegistry registry) {
    if (alreadyRegisteredWith(registry)) {
      return;
    }
 FlutterMusicPlugin.registerWith(registry.registrarFor("com.plugin.FlutterMusicPlugin"));
  }

  private static boolean alreadyRegisteredWith(PluginRegistry registry) {
    final String key = GeneratedPluginRegistrant.class.getCanonicalName();
    if (registry.hasPlugin(key)) {
      return true;
    }
    registry.registrarFor(key);
    return false;
  }
}

注冊人

? 它對應(yīng)的是代碼中的GeneratedPluginRegistrant類

  • 發(fā)起注冊

    GeneratedPluginRegistrant類中的

     FlutterMusicPlugin.registerWith(registry.registrarFor("com.plugin.FlutterMusicPlugin"));//即為發(fā)起注冊點(diǎn)
    
  • 通過注冊商更新注冊

    FlutterMusicPlugin類中的

    registrar.addActivityResultListener(plugin);//即為通過注冊商更新了需要Activity回調(diào)的信息
    
  • 同步給注冊局

    sdk中的FlutterRegistrar類

    FlutterPluginRegistry.this.mActivityResultListeners.add(listener);//即為把信息同步給了注冊局
    

注冊商

? 它對應(yīng)的是代碼中的FlutterPluginRegistry內(nèi)部類FlutterRegistrar。

? 不看不知道,"注冊商"其實(shí)給我們提供了很多功能,比如獲取activity,viewDestory的生命周期的回調(diào),獲取surfaceTexture等等,真是一個能力強(qiáng)大的"注冊商"。

      
        Activity activity();//返回 Host app的Activity
        Context context();//返回 Application Context.
        Context activeContext();//返回 活動Context
        //返回 BinaryMessenger 主要用來注冊Platform channels
        BinaryMessenger messenger();
        //返回 TextureRegistry,從里面可以拿到SurfaceTexture 
        TextureRegistry textures();
        //返回 當(dāng)前Host app創(chuàng)建的FlutterView
        FlutterView view();
        //返回Asset對應(yīng)的文件路徑
        String lookupKeyForAsset(String var1);
        //返回Asset對應(yīng)的文件路徑
        String lookupKeyForAsset(String var1, String var2);
        //插件對外發(fā)布的一個"值"
        PluginRegistry.Registrar publish(Object var1);
        //注冊權(quán)限相關(guān)的回調(diào)
        PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener var1);
        //注冊ActivityResult回調(diào)
        PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener var1);
        //注冊NewIntent回調(diào)
        PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener var1);
        //注冊UserLeaveHint回調(diào)
        PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener var1);
        //注冊View銷毀回調(diào)
        PluginRegistry.Registrar addViewDestroyListener(PluginRegistry.ViewDestroyListener var1);

注冊局

? 它對應(yīng)的是代碼中的FlutterPluginRegistry

pluginregister.png

從成員變量可以看出FlutterPluginRegistry主要維護(hù)兩類信息:

  1. 注冊插件唯一標(biāo)識信息匯總
  2. FlutterRegistrar所開放的那些功能(比如:addActivityResultListener)的信息匯總
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容