日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?Flutter實現原理淺析_Android

作者:失落夏天 ? 更新時間: 2022-10-05 編程語言

前言

flutter可以說是當下最流行的跨平臺技術了,其最突出的

網上可以搜到的文章,大多數都是flutter的用法,即使介紹其實現原理的,也直接深入源碼直接解讀,造成只有一定功能的讀者才能理解。

本文希望以最通俗易解的方式介紹flutter的實現原理,也許不會介紹的深入或者詳細,但是一定能讓讀者知道flutter的基本實現原理。

本文基于flutter2.0的源碼進行原理分析,3.0的源碼有些許變動,但整體流程是一樣的。

一.安卓原生界面繪制的流程

原生繪制流程

有另外的一個系列文章來講原生的界面,為了方便讀者閱讀,本文會簡略描述一下整個流程。

其主要流程是在每次sync的時候去執行測量(measure),布局(layout),繪制(draw)的流程。

而draw的時候時候,核心是利用canvas執行各種繪制命令,并且把這些命令轉換為buffer記錄,最終發送給WMS層,然后轉交給SurfaceFlinger,由其做最終的合成和渲染。

SurfaceView繪制流程

另外也許你還聽說過另外一種可以在子線程渲染的控件:surfaceView。我們的視頻播放器,高頻繪制的自定義View都是由其實現的。

其主要流程圖如下:

其原理其實和第一種方式類似,區別就是在于少了measure,layout的流程。而是自己去計算坐標,然后直接進入draw的流程,通過canvas寫入native的數據buffer內存中,最后統一發送給WMS進行進入渲染的流程。

而Flutter的實現原理,其實就和surfaceView類似。

二.Flutter上界面繪制的流程

flutter有混合開發和純flutter開發兩種。純flutter使用的是FlutterActivity,而混合開發一般使用的是FlutterView。我們先看一下使用FlutterActivity的方式。

FlutterActivity中的流程

首先看一下FlutterActivity的實現,發現其核心流程都交給了FlutterActivityDelegate處理,所以我們直接看Delegate的onCreate方法:

public void onCreate(Bundle savedInstanceState) {
        ...
        this.flutterView = this.viewFactory.createFlutterView(this.activity);
        if (this.flutterView == null) {
            FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
            this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
            this.flutterView.setLayoutParams(matchParent);
            this.activity.setContentView(this.flutterView);
            this.launchView = this.createLaunchView();
            if (this.launchView != null) {
                this.addLaunchView();
            }
        }
        ...
    }

主要流程就是創建一個flutterView,添加到contentView中,所以其實無論哪種方式,最終都是由flutterView來實現的。

FlutterView中的實現

首先我們看一下FlutterView類,發現其繼承自SurfaceView,這也回應了我們上面的描述,其核心實現原理就是基于surfaceView實現的。

其構造方法如下:非核心代碼已做了刪減處理

public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
            super(context, attrs);
            ...
            //創建在native層的處理對象,相關繪制邏輯其實都是在native層處理的,Java層只負責傳入
            this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
            //創建dart的解釋器
            this.dartExecutor = this.mNativeView.getDartExecutor();
            //創建渲染對象
            this.flutterRenderer = new FlutterRenderer(this.mNativeView.getFlutterJNI());
            //native層的view對象進行綁定   
            this.mNativeView.attachViewAndActivity(this, activity);
            //由于是surfaceView,所以在surface創建好之后傳入naitve
            this.mSurfaceCallback = new Callback() {
                public void surfaceCreated(SurfaceHolder holder) {
                    FlutterView.this.assertAttached();
                    FlutterView.this.mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());
                }
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                    FlutterView.this.assertAttached();
                    FlutterView.this.mNativeView.getFlutterJNI().onSurfaceChanged(width, height);
                }
                public void surfaceDestroyed(SurfaceHolder holder) {
                    FlutterView.this.assertAttached();
                    FlutterView.this.mNativeView.getFlutterJNI().onSurfaceDestroyed();
                }
            };
            this.getHolder().addCallback(this.mSurfaceCallback);
            //
            this.mActivityLifecycleListeners = new ArrayList();
            this.mFirstFrameListeners = new ArrayList();
            this.navigationChannel = new NavigationChannel(this.dartExecutor);
            this.keyEventChannel = new KeyEventChannel(this.dartExecutor);
            this.lifecycleChannel = new LifecycleChannel(this.dartExecutor);
            this.localizationChannel = new LocalizationChannel(this.dartExecutor);
            this.platformChannel = new PlatformChannel(this.dartExecutor);
            this.systemChannel = new SystemChannel(this.dartExecutor);
            this.settingsChannel = new SettingsChannel(this.dartExecutor);
            final PlatformPlugin platformPlugin = new PlatformPlugin(activity, this.platformChannel);
            this.addActivityLifecycleListener(new ActivityLifecycleListener() {
                public void onPostResume() {
                    platformPlugin.updateSystemUiOverlays();
                }
            });
            this.mImm = (InputMethodManager)this.getContext().getSystemService("input_method");
            PlatformViewsController platformViewsController = this.mNativeView.getPluginRegistry().getPlatformViewsController();
            this.mTextInputPlugin = new TextInputPlugin(this, this.dartExecutor, platformViewsController);
            this.androidKeyProcessor = new AndroidKeyProcessor(this.keyEventChannel, this.mTextInputPlugin);
            this.androidTouchProcessor = new AndroidTouchProcessor(this.flutterRenderer);
            this.mNativeView.getPluginRegistry().getPlatformViewsController().attachTextInputPlugin(this.mTextInputPlugin);
            this.sendLocalesToDart(this.getResources().getConfiguration());
            this.sendUserPlatformSettingsToDart();

其構造方法中,主要流程就是各種功能的初始化,以及完成surface和native的綁定。

我們可以看到下面這樣代碼,就是把surface傳入了native層。

FlutterView.this.mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());

所以看到這里,我們可以做這樣的推測了:

flutter原理其實就類似于surfaceView的實現。通過傳遞surface到native層,然后通過這個surface獲取到canvas,寫入渲染buffer,最終通知到WMS完成繪制的整個流程。

native流程

onSurfaceCreated的創建最終會走到native層platform_view_android_jni_impl.cpp中的SurfaceCreated()方法。

static void SurfaceCreated(JNIEnv* env,
                           jobject jcaller,
                           jlong shell_holder,
                           jobject jsurface) {
  // Note: This frame ensures that any local references used by
  // ANativeWindow_fromSurface are released immediately. This is needed as a
  // workaround for https://code.google.com/p/android/issues/detail?id=68174
  fml::jni::ScopedJavaLocalFrame scoped_local_reference_frame(env);
  auto window = fml::MakeRefCounted<AndroidNativeWindow>(
      ANativeWindow_fromSurface(env, jsurface));
  ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyCreated(std::move(window));
}

這里很簡單,創建native層的Window對象,調用NotifyCreated方法繼續傳入。

走到platform_view.cc的NotifyCreated方法如下:

void PlatformViewAndroid::NotifyCreated(
    fml::RefPtr<AndroidNativeWindow> native_window) {
  if (android_surface_) {
    //1
    InstallFirstFrameCallback();
    ...
  }
  //2
  PlatformView::NotifyCreated();
}

該方法中主要做了兩件事:

第一件:回調java的onFirstFrame方法;

第二件:啟動渲染流程。

NotifyCreated中,主要是交給delegate_去處理:

void PlatformView::NotifyCreated() {
  std::unique_ptr<Surface> surface;
  ...
  delegate_.OnPlatformViewCreated(std::move(surface));
}

這個delegate_其實是shell對象,則會調用到shell.cc的OnPlatformViewCreated方法:

// |PlatformView::Delegate|
void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
  TRACE_EVENT0("flutter", "Shell::OnPlatformViewCreated");
  FML_DCHECK(is_setup_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
 
  ...
  //這里主要是一系列的判斷,避免死鎖
  const bool should_post_raster_task =
      !task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread();
 
  fml::AutoResetWaitableEvent latch;
  //UI線程執行,渲染的流程
  auto raster_task =
      fml::MakeCopyable([&waiting_for_first_frame = waiting_for_first_frame_,
                         rasterizer = rasterizer_->GetWeakPtr(),  //
                         surface = std::move(surface)]() mutable {
        if (rasterizer) {
          // Enables the thread merger which may be used by the external view
          // embedder.
          rasterizer->EnableThreadMergerIfNeeded();
          rasterizer->Setup(std::move(surface));
        }
 
        waiting_for_first_frame.store(true);
      });
  ...
    auto ui_task = [engine = engine_->GetWeakPtr()] {
    if (engine) {
      engine->OnOutputSurfaceCreated();
    }
  };
  ...
    //啟動各種渲染的流程
    fml::TaskRunner::RunNowOrPostTask(task_runners_.GetIOTaskRunner(), io_task);
    latch.Wait();
  if (!should_post_raster_task) {
    // See comment on should_post_raster_task, in this case the raster_task
    // wasn't executed, and we just run it here as the platform thread
    // is the raster thread.
    raster_task();
  }
}

這個方法中,主要就是各種檢查,包括一些鎖機制的判斷,最后通知engine啟動去渲染surface了

三.總結

Flutter的簡單實現原理

Flutter的簡單實現原理其實就類似于surfaceView的實現。

surfaceView中往buffer中寫入渲染數據是通過java層的canvas實現的,而在flutter中是通過native層實現。flutter就是在native層接收到surface,然后通過surface獲取到native層的canvas,對buffer進行寫入,最終通知到WMS完成繪制的整個流程。

當然,詳細的原理還包含了事件流程是如何分發的,如何翻譯dart成可執行的代碼,如何解釋編譯的產物等等,由于篇幅限制,本篇就不詳細展開了,后續會逐漸寫文章進行原理分析。

Flutter的幾個高頻問題

1.為什么主要流程使用jni實現?用Java實現是否可以?

我的理解是其實java實現也是完全可以的,但是要知道flutter是跨平臺的。如果用java的話,那么在安卓上是沒問題的,但是如果在IOS勢必又要用OC在寫一套邏輯,這樣造成重復的工作量。而使用C來編寫,任意平臺其實都是可以通用的,降低開發成本,而且更不容易出現差異。之前和螞蟻金服antv(螞蟻數據可視化團隊)的朋友聊天時,他們也是類似的考慮,底層邏輯使用C實現,安卓/IOS/PC等只做上層的接口封裝和兼容。

2.為什么使用dart而不使用其他語言?

這個我的理解是用JS應該也是可以的,或者說java也可以。但是又都不夠好。

如果是用java的話,flutter的熱部署功能就無法實現,java類加載機制有緩存,一旦加載就無法被替換。當然不是絕對的,可以通過替換classLoader的方式進行替換,類似于tomcat的熱部署。但如果這樣,實現成本就會及其的高,而且性能不佳。

使用js的話,實現熱部署肯定是沒有問題,但問題就在于生產環境,其實更需要的是效率。JIT的編譯方式效率肯定是比不過AOT的。

而dart同時支持AOT和JIT兩種方式,自然是最優的選擇。

原文鏈接:https://blog.csdn.net/rzleilei/article/details/126165230

欄目分類
最近更新