欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android Flutter實(shí)現(xiàn)原理淺析

 更新時(shí)間:2022年08月10日 11:29:15   作者:失落夏天  
這篇文章主要介紹了Android Flutter的實(shí)現(xiàn)原理是怎么樣的,flutter可以說是當(dāng)下最流行的跨平臺(tái)技術(shù)了,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

flutter可以說是當(dāng)下最流行的跨平臺(tái)技術(shù)了,其最突出的

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

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

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

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

原生繪制流程

有另外的一個(gè)系列文章來講原生的界面,為了方便讀者閱讀,本文會(huì)簡(jiǎn)略描述一下整個(gè)流程。

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

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

SurfaceView繪制流程

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

其主要流程圖如下:

其原理其實(shí)和第一種方式類似,區(qū)別就是在于少了measure,layout的流程。而是自己去計(jì)算坐標(biāo),然后直接進(jìn)入draw的流程,通過canvas寫入native的數(shù)據(jù)buffer內(nèi)存中,最后統(tǒng)一發(fā)送給WMS進(jìn)行進(jìn)入渲染的流程。

而Flutter的實(shí)現(xiàn)原理,其實(shí)就和surfaceView類似。

二.Flutter上界面繪制的流程

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

FlutterActivity中的流程

首先看一下FlutterActivity的實(shí)現(xiàn),發(fā)現(xiàn)其核心流程都交給了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();
            }
        }
        ...
    }

主要流程就是創(chuàng)建一個(gè)flutterView,添加到contentView中,所以其實(shí)無論哪種方式,最終都是由flutterView來實(shí)現(xiàn)的。

FlutterView中的實(shí)現(xiàn)

首先我們看一下FlutterView類,發(fā)現(xiàn)其繼承自SurfaceView,這也回應(yīng)了我們上面的描述,其核心實(shí)現(xiàn)原理就是基于surfaceView實(shí)現(xiàn)的。

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

public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
            super(context, attrs);
            ...
            //創(chuàng)建在native層的處理對(duì)象,相關(guān)繪制邏輯其實(shí)都是在native層處理的,Java層只負(fù)責(zé)傳入
            this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
            //創(chuàng)建dart的解釋器
            this.dartExecutor = this.mNativeView.getDartExecutor();
            //創(chuàng)建渲染對(duì)象
            this.flutterRenderer = new FlutterRenderer(this.mNativeView.getFlutterJNI());
            //native層的view對(duì)象進(jìn)行綁定   
            this.mNativeView.attachViewAndActivity(this, activity);
            //由于是surfaceView,所以在surface創(chuàng)建好之后傳入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();

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

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

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

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

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

native流程

onSurfaceCreated的創(chuàng)建最終會(huì)走到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));
}

這里很簡(jiǎn)單,創(chuàng)建native層的Window對(duì)象,調(diào)用NotifyCreated方法繼續(xù)傳入。

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

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

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

第一件:回調(diào)java的onFirstFrame方法;

第二件:?jiǎn)?dòng)渲染流程。

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

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

這個(gè)delegate_其實(shí)是shell對(duì)象,則會(huì)調(diào)用到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線程執(zhí)行,渲染的流程
  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();
    }
  };
  ...
    //啟動(dòng)各種渲染的流程
    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();
  }
}

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

三.總結(jié)

Flutter的簡(jiǎn)單實(shí)現(xiàn)原理

Flutter的簡(jiǎn)單實(shí)現(xiàn)原理其實(shí)就類似于surfaceView的實(shí)現(xiàn)。

surfaceView中往buffer中寫入渲染數(shù)據(jù)是通過java層的canvas實(shí)現(xiàn)的,而在flutter中是通過native層實(shí)現(xiàn)。flutter就是在native層接收到surface,然后通過surface獲取到native層的canvas,對(duì)buffer進(jìn)行寫入,最終通知到WMS完成繪制的整個(gè)流程。

當(dāng)然,詳細(xì)的原理還包含了事件流程是如何分發(fā)的,如何翻譯dart成可執(zhí)行的代碼,如何解釋編譯的產(chǎn)物等等,由于篇幅限制,本篇就不詳細(xì)展開了,后續(xù)會(huì)逐漸寫文章進(jìn)行原理分析。

Flutter的幾個(gè)高頻問題

1.為什么主要流程使用jni實(shí)現(xiàn)?用Java實(shí)現(xiàn)是否可以?

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

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

這個(gè)我的理解是用JS應(yīng)該也是可以的,或者說java也可以。但是又都不夠好。

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

使用js的話,實(shí)現(xiàn)熱部署肯定是沒有問題,但問題就在于生產(chǎn)環(huán)境,其實(shí)更需要的是效率。JIT的編譯方式效率肯定是比不過AOT的。

而dart同時(shí)支持AOT和JIT兩種方式,自然是最優(yōu)的選擇。

到此這篇關(guān)于Android Flutter實(shí)現(xiàn)原理淺析的文章就介紹到這了,更多相關(guān)Android Flutter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android實(shí)現(xiàn)仿魅族日歷首頁功能

    Android實(shí)現(xiàn)仿魅族日歷首頁功能

    這篇文章主要介紹了Android實(shí)現(xiàn)仿魅族日歷首頁功能的實(shí)現(xiàn)過程以及相關(guān)代碼講解分享,對(duì)此有興趣的朋友參考下。
    2018-02-02
  • arcgis android之地圖圖層切換

    arcgis android之地圖圖層切換

    本篇文章主要介紹了arcgis android之地圖圖層切換,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • Android開發(fā)實(shí)現(xiàn)簡(jiǎn)單的觀察者與被觀察者示例

    Android開發(fā)實(shí)現(xiàn)簡(jiǎn)單的觀察者與被觀察者示例

    這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)簡(jiǎn)單的觀察者與被觀察者,簡(jiǎn)單描述了觀察者模式的概念、原理并結(jié)合實(shí)例形式分析了Android實(shí)現(xiàn)觀察者模式的簡(jiǎn)單操作技巧,需要的朋友可以參考下
    2017-11-11
  • Android ListView之setEmptyView正確使用方法

    Android ListView之setEmptyView正確使用方法

    這篇文章主要介紹了Android ListView之setEmptyView正確使用方法的相關(guān)資料,希望通過本文能幫助到大家使用該方法,需要的朋友可以參考下
    2017-09-09
  • 詳解Android控件狀態(tài)依賴框架

    詳解Android控件狀態(tài)依賴框架

    這篇文章主要為大家詳細(xì)介紹了Android控件狀態(tài)依賴框架的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android Studio升級(jí)4.1.1后各種錯(cuò)誤和解決方案

    Android Studio升級(jí)4.1.1后各種錯(cuò)誤和解決方案

    這篇文章主要介紹了Android Studio升級(jí)4.1.1后各種錯(cuò)誤和解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • android驗(yàn)證郵箱輸入是否合法

    android驗(yàn)證郵箱輸入是否合法

    這篇文章主要為大家詳細(xì)介紹了android驗(yàn)證郵箱輸入是否合法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • Android 使用fast-verification實(shí)現(xiàn)驗(yàn)證碼填寫功能的實(shí)例代碼

    Android 使用fast-verification實(shí)現(xiàn)驗(yàn)證碼填寫功能的實(shí)例代碼

    這篇文章主要介紹了Android 使用fast-verification實(shí)現(xiàn)驗(yàn)證碼填寫功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Android:“萬能”Activity重構(gòu)篇

    Android:“萬能”Activity重構(gòu)篇

    本文主要介紹了mvp以及每一層,以及使用mvp來重構(gòu)“萬能”Activity,其實(shí)每一層需要注意的東西還有很多,比如model層是最難寫的一層。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • 基于Android RxCache使用方法詳解

    基于Android RxCache使用方法詳解

    下面小編就為大家分享一篇基于Android RxCache使用方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01

最新評(píng)論