文章目錄
- 前言
- Flutter渲染模式
- FlutterSurfaceView分析
- FlutterTextureView分析
- FlutterImageView分析
- FlutterRender分析
- FlutterView分析
- 總結(類圖,架構圖)
- 類關系圖
- 架構圖
前言
? 通過前面文章的分析我們了解到FlutterActivity的顯示最終是通過FlutterView進行渲染,本文我們深入FlutterView的原始碼來具體分析下Flutter UI是如何一步步顯示到Activity,又是如何跟Flutter Engine關聯,下面來看一下FlutterView的大致相關類:

Flutter渲染模式
要了解FlutterView我們首先來了解一下Flutter的RenderMode,在Flutter里面渲染模式分為三種:RenderMode.surface、RenderMode.texture、RenderMode.image,前面兩種模式是在介面FlutterActivityAndFragmentDelegate.Host介面getRenderMode()方法中回傳,其內部的判斷條件在FlutterActivity和FlutterFragment中是不一樣的:
-
FlutterActivity
public RenderMode getRenderMode() { return getBackgroundMode() == BackgroundMode.opaque ? RenderMode.surface : RenderMode.texture; }說白了在FlutterActivity中RenderMode就是根據是否透明來決定,如果是透明表單那么就使用
RenderMode.texture,如果是不透明的就是用RenderMode.surface -
FlutterFragment
public RenderMode getRenderMode() { String renderModeName = getArguments().getString(ARG_FLUTTERVIEW_RENDER_MODE, RenderMode.surface.name()); return RenderMode.valueOf(renderModeName); }而在FlutterFragment中RenderMode是通過
ARG_FLUTTERVIEW_RENDER_MODE引數來決定,
思考:為什么透明模式下使用
RenderMode.texture,而不透明模式下使用RenderMode.surface
顯而易見三種渲染模式對應的在FlutterView創建時以來不同的類,分別是:FlutterSurfaceView,FlutterTextureView,FlutterImageView,下面我們一起來看看這三個類,
FlutterSurfaceView分析
從文中開頭大致的類圖關系我們知道FlutterSurfaceView、FlutterTextureView和FlutterImageView都是FlutterView的一個成員變數,通過建構式根據不同的渲染模式傳遞對應的引數對FlutterView進行初始化,
//繼承自SurfaceView,實作RenderSurface介面
public class FlutterSurfaceView extends SurfaceView implements RenderSurface {
private final SurfaceHolder.Callback surfaceCallback =
new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
//......
connectSurfaceToRenderer();
}
@Override
public void surfaceChanged(
@NonNull SurfaceHolder holder, int format, int width, int height) {
//....
changeSurfaceSize(width, height);
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
//...
disconnectSurfaceFromRenderer();
}
};
private void connectSurfaceToRenderer() {
if (flutterRenderer == null || getHolder() == null) {
throw new IllegalStateException(
"connectSurfaceToRenderer() should only be called when flutterRenderer and getHolder() are non-null.");
}
flutterRenderer.startRenderingToSurface(getHolder().getSurface());
}
/**
* 當 FlutterSurfaceView 想要開始將 Flutter UI 渲染到此 FlutterSurfaceView 時,由此 FlutterSurfaceView 的所有者呼叫,
* 如果 Android android.view.Surface 可用,則此方法會將 android.view.Surface 提供給給定的 FlutterRenderer 以開始將 Flutter 的 UI 渲染到此 *FlutterSurfaceView,
* 如果還沒有 Android android.view.Surface 可用,則此 FlutterSurfaceView 將等到 android.view.Surface 可用,然后將該
* android.view.Surface 提供給給定的 FlutterRenderer 以開始將 Flutter 的 UI 渲染到此 FlutterSurfaceView,
*/
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
connectSurfaceToRenderer();
}
/***
當 FlutterSurfaceView 不再想將 Flutter UI 渲染到此 FlutterSurfaceView 時,由此 FlutterSurfaceView 的所有者呼叫,此方法將停止從 Flutter 到此 FlutterSurfaceView 的任何正在進行的渲染,
***/
public void detachFromRenderer() {
disconnectSurfaceFromRenderer();
}
// FlutterRenderer and getSurfaceTexture() must both be non-null.
private void connectSurfaceToRenderer() {
flutterRenderer.startRenderingToSurface(getHolder().getSurface());
}
// FlutterRenderer must be non-null.
private void changeSurfaceSize(int width, int height) {
flutterRenderer.surfaceChanged(width, height);
}
// FlutterRenderer must be non-null.
private void disconnectSurfaceFromRenderer() {
flutterRenderer.stopRenderingToSurface();
}
}
? 上面的代碼邏輯相當簡介易懂,可以看到,FlutterSurfaceView實際上是一個SurfaceView,用法也是跟SurfaceView一樣,只是渲染資料是最終是通過flutterJNI作為橋梁實作Flutter Engine與Android View層進行資料傳遞實作界面繪制的,
FlutterTextureView分析
與上面的FlutterSurfaceView一樣,邏輯實作簡潔易懂,先看看主要邏輯:
//繼承自TextureView,實作RenderSurface介面
public class FlutterTextureView extends TextureView implements RenderSurface {
private final SurfaceTextureListener surfaceTextureListener =
new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(
SurfaceTexture surfaceTexture, int width, int height) {
connectSurfaceToRenderer();
}
@Override
public void onSurfaceTextureSizeChanged(
@NonNull SurfaceTexture surface, int width, int height) {
changeSurfaceSize(width, height);
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
// Invoked every time a new frame is available. We don't care.
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
disconnectSurfaceFromRenderer();
return true;
}
};
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
connectSurfaceToRenderer();
}
public void detachFromRenderer() {
disconnectSurfaceFromRenderer();
}
private void connectSurfaceToRenderer() {
renderSurface = new Surface(getSurfaceTexture());
flutterRenderer.startRenderingToSurface(renderSurface);
}
private void changeSurfaceSize(int width, int height) {
flutterRenderer.surfaceChanged(width, height);
}
private void disconnectSurfaceFromRenderer() {
flutterRenderer.stopRenderingToSurface();
if (renderSurface != null) {
renderSurface.release();
renderSurface = null;
}
}
}
從上面的代碼可以看到FlutterTextureView和FlutterSurfaceView的邏輯基本一致,唯一不同的就是提供的Surface來源不一樣,邏輯很簡單這里不做多余介紹,
FlutterImageView分析
FlutterImageView并不是一個真正意義上的ImageView,它的作業流程和FlutterTextureView,FlutterSurfaceView作業流程極度相似,但是它的使用場景卻完全不一樣,想要了解FlutterImageView的作業場景,必須要先了解Flutter的Hybrid Composition作業模式,由于Hybrid Composition 模式涉及到的內容關聯比較多,下次單獨講解,這里簡單理解來講Hybrid Composition模式就是解決原生控制元件和Flutter混合顯示問題,
我們來看下FlutterImageView原始碼:
@TargetApi(19)
public class FlutterImageView extends View implements RenderSurface {
// 原生控制元件的繪制操作
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!imageQueue.isEmpty()) {
if (currentImage != null) {
currentImage.close();
}
currentImage = imageQueue.poll();
updateCurrentBitmap();
}
if (currentBitmap != null) {
canvas.drawBitmap(currentBitmap, 0, 0, null);
}
}
}
我們可以看到FlutterImageView實際上就是一個原生的View,但是它又實作了RenderSurface介面,不難判斷FlutterImageView既可以顯示渲染我們的FlutterUI,又可以顯示渲染我們的原生View,它的使用場景已經原理分享后面再花費專題文章講解,
FlutterRender分析
通過上面的分析,我們知道FlutterRenderer 的主要職責最終是通過 FlutterJNI 進行渲染關聯處理,與原生平臺提供的 FlutterSurfaceView、FlutterTextureView 、FlutterImageView進行純 UI 渲染,將 Flutter 像素繪制到 Android 視圖層次結構,
public class FlutterRenderer implements TextureRegistry {
//......
@NonNull private final FlutterJNI flutterJNI;
@Nullable private Surface surface;
//......
}
通過上面原始碼的兩個屬性成員就能看出來他的職責,
FlutterView分析
通俗來說FlutterView 的作用是在 Android 設備上顯示一個 Flutter UI,繪制內容來自于 FlutterEngine 的flutterJNI提供,FlutterView常用模式下有兩種渲染模式:
-
RenderMode.surface
這種模式性能最好,但是這種模式下的一個 FlutterView 不能定位在 z-index 中其他 2 個 Android Views 之間,也不能進行影片/轉換,除非需要 android.graphics.SurfaceTexture 的特殊功能,否則強烈建議開發人員使用這種渲染模式,
-
RenderMode.texture
它將 Flutter UI 繪制到 android.graphics.SurfaceTexture,這種模式的性能不如 io.flutter.embedding.android.RenderMode.surface,但這種模式下的 FlutterView 可以進行影片和變換,也可以定位在 2+ 其他 Android 視圖之間的 z-index 中,除非需要 android.graphics.SurfaceTexture 的特殊功能,否則開發人員應該強烈推薦
FlutterView 的默認構造器就是 surface 模式
下面我們再來分析下FlutterView,首先我們來看看它的變數和建構式宣告
public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseCursorViewDelegate {
private static final String TAG = "FlutterView";
// 用來真正渲染繪制視圖的相關類
@Nullable private FlutterSurfaceView flutterSurfaceView;
@Nullable private FlutterTextureView flutterTextureView;
@Nullable private FlutterImageView flutterImageView;
@Nullable private RenderSurface renderSurface;
@Nullable private RenderSurface previousRenderSurface;
//與 FlutterEngine連接
@Nullable private FlutterEngine flutterEngine;
// 處理各種型別的 Android View 輸入和事件的組件
@Nullable private MouseCursorPlugin mouseCursorPlugin;
@Nullable private TextInputPlugin textInputPlugin;
@Nullable private LocalizationPlugin localizationPlugin;
@Nullable private AndroidKeyProcessor androidKeyProcessor;
@Nullable private AndroidTouchProcessor androidTouchProcessor;
@Nullable private AccessibilityBridge accessibilityBridge;
//建構式,默認模式為surface
private FlutterView(
@NonNull Context context,
@Nullable AttributeSet attrs,
@NonNull FlutterSurfaceView flutterSurfaceView) {
super(context, attrs);
this.flutterSurfaceView = flutterSurfaceView;
this.renderSurface = flutterSurfaceView;
init();
}
//建構式,模式為texture
private FlutterView(
@NonNull Context context,
@Nullable AttributeSet attrs,
@NonNull FlutterTextureView flutterTextureView) {
super(context, attrs);
this.flutterTextureView = flutterTextureView;
this.renderSurface = flutterTextureView;
init();
}
//建構式 模式為image
@TargetApi(19)
private FlutterView(
@NonNull Context context,
@Nullable AttributeSet attrs,
@NonNull FlutterImageView flutterImageView) {
super(context, attrs);
this.flutterImageView = flutterImageView;
this.renderSurface = flutterImageView;
init();
}
//根據不同的模式指定RenderSurface
private void init() {
if (flutterSurfaceView != null) {
addView(flutterSurfaceView);
} else if (flutterTextureView != null) {
addView(flutterTextureView);
} else {
addView(flutterImageView);
}
}
通過上面的代碼我們知道FlutterView其實是一個原生的繼承自FrameLayout的ViewGroup,在init中根據不同的模式添加不同的View從而指定surface,也就是 FlutterSurfaceView、FlutterTextureView、FlutterImageView 之一,而最終FlutterEngine渲染資料到不同的surface,
總結(類圖,架構圖)
類關系圖

架構圖

圖是按照理解繪制的,比較粗略有問題歡迎留言
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/335202.html
標籤:其他
