[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
時序圖

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
- 初始化標(biāo)記位:snapshot文件集成的方式。
- sIsPrecompiledAsSharedLibrary 代表的是把所有的snapshot文件打包成一個動態(tài)庫(一種類似ios的集成方式)。
- 禁止同時采用兩種集成方式。
-
initResource
- 創(chuàng)建了一個ResourceExtractor 對象,他是Resource文件的搬運(yùn)工
- 通過ResourceExtractor 對象的addResource方法初始化需要搬運(yùn)的文件
- 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)聚性

FlutterView
可以先簡單的把FlutterView看成是負(fù)責(zé)顯示的,而把后面的FlutterNativeView看成是負(fù)責(zé)通信的。
-
解偶系統(tǒng)控件
首先我們可以看到FlutterView是繼承自SurfaceView的,提到SurfaceView我們肯定會想到“挖洞”,“雙緩沖”這些詞,也正是因?yàn)檫@些特性FlutterView可以很好的把UI渲染工作交給Flutter( 后者通過dart->組裝LayerTree->Skia完成繪制 )。

-
傳遞狀態(tài)消息給Dart UI
這些消息大致可以將它們分成七個模塊,兩大類
-
通過反射原生系統(tǒng)的api進(jìn)行數(shù)據(jù)通訊
多語言模塊、系統(tǒng)信息和用戶設(shè)置
-
將數(shù)據(jù)打包成特殊格式以消息的形式和使用Dart編寫的flutter控件交互
生命周期、按鍵消息、路由導(dǎo)航和平臺插件
-
FlutterNativeView
可以先簡單的把FlutterNativeView看成是負(fù)責(zé)通信的。它在系統(tǒng)層面上實(shí)現(xiàn)了BinaryMessenger接口 [這在下文Transmitter中詳細(xì)介紹]。
Transmitter
傳遞者
消息渠道
-
Flutter針對不同的應(yīng)用場景封裝了3類Channel
- MethodChannel:調(diào)用方法
- BasicMessageChannel:自定義結(jié)構(gòu)信息
- EventChannel:事件的通知
-
3類Channel擁有相似的結(jié)構(gòu)類型
- 信使BinaryMessenger:我們自己創(chuàng)建的channel一般就是FlutterNativeView
- channel 名:channel的key值,不可重復(fù)
- MethodCodec /MessageCodec 解碼器: 針對不同的channle解碼二進(jìn)制應(yīng)答數(shù)據(jù)

消息編解碼
? 標(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)系如下)

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

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

從成員變量可以看出FlutterPluginRegistry主要維護(hù)兩類信息:
- 注冊插件唯一標(biāo)識信息匯總
- FlutterRegistrar所開放的那些功能(比如:addActivityResultListener)的信息匯總