移動開發技術的進化歷程(原生開發與跨平臺技術)

原生開發

原生應用程序是指某一個移動平臺(比如iOS或安卓)所特有的應用,使用相應平臺支持的開發工具和語言,並直接調用系統提供的SDK API。比如 Android 原生應用就是指使用 Java 或 Kotlin 語言直接調用Android SDK開發的應用程序;而 iOS 原生應用就是指通過 Objective-C 或 Swift 語言直接調用iOS SDK開發的應用程序。

優點:

  • 可訪問平臺全部功能(GPS、攝像頭);
  • 速度快、性能高、可以實現複雜動畫及繪製,整體用戶體驗好;

缺點:

  • 平臺特定,開發成本高;不同平臺必須維護不同代碼,人力成本隨之變大;
  • 內容固定,動態化弱,大多數情況下,有新功能更新時只能發版;

純原生開發主要面臨動態化和開發成本兩個問題,而針對這兩個問題,誕生了一些跨平臺的動態化框架。

跨平臺技術

根據跨平臺原理,主要分爲三類:

  • H5 + 原生(Cordova、Ionic、微信小程序)
  • JavaScript開發 + 原生渲染(React Native、Weex、快應用)
  • 自繪UI + 原生(QT for mobile、Flutter

Hybrid 技術

主要原理就是將 APP 的一部分需要動態變動的內容通過 H5 來實現,通過原生的網頁加載控件WebView (Android)或 WKWebView(iOS)來加載(以後若無特殊說明,我們用WebView來統一指代android和iOS中的網頁加載控件)。稱這種方式爲混合開發,採用混合模式開發的APP稱之爲混合應用或Hybrid APP ,如果一個應用的大多數功能都是H5實現的話,我們稱其爲Web APP

原生開發可以訪問平臺所有功能,而混合開發中,H5代碼是運行在WebView中,而WebView實質上就是一個瀏覽器內核,其JavaScript依然運行在一個權限受限的沙箱中,所以對於大多數系統能力都沒有訪問權限,如無法訪問文件系統、不能使用藍牙等。所以,對於H5不能實現的功能,都需要原生去做。而混合框架一般都會在原生代碼中預先實現一些訪問系統能力的API, 然後暴露給WebView以供JavaScript調用,這樣一來,WebView就成爲了JavaScript與原生API之間通信的橋樑,主要負責JavaScript與原生之間傳遞調用消息,而消息的傳遞必須遵守一個標準的協議,它規定了消息的格式與含義,我們把依賴於WebView的用於在JavaScript與原生之間通信並實現了某種消息傳輸協議的工具稱之爲WebView JavaScript Bridge, 簡稱 JsBridge,它也是混合開發框架的核心。

JavaScript開發 與 原生渲染

React Native (簡稱RN)是Facebook於2015年4月開源的跨平臺移動應用開發框架,是Facebook早先開源的JS框架 React 在原生移動應用平臺的衍生產物,目前支持iOS和Android兩個平臺。RN使用Javascript 語言,類似於HTML的 JSX,以及 CSS 來開發移動應用,因此熟悉Web前端開發的技術人員只需很少的學習就可以進入移動應用開發領域。

由於RN和React原理相通,並且Flutter也是受React啓發,很多思想也都是相通的,萬丈高樓平地起,我們有必要深入瞭解一下React原理。React是一個響應式的Web框架,我們先了解一下兩個重要的概念:DOM樹與響應式編程。

DOM樹與控件樹
文檔對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴展標誌語言的標準編程接口,一種獨立於平臺和語言的方式訪問和修改一個文檔的內容和結構。換句話說,這是表示和處理一個HTML或XML文檔的標準接口。簡單來說,DOM就是文檔樹,與用戶界面控件樹對應,在前端開發中通常指HTML對應的渲染樹,但廣義的DOM也可以指Android中的XML佈局文件對應的控件樹,而術語DOM操作就是指直接來操作渲染樹(或控件樹), 因此,可以看到其實DOM樹和控件樹是等價的概念,只不過前者常用於Web開發中,而後者常用於原生開發中。

響應式編程
React中提出一個重要思想:狀態改變則UI隨之自動改變,而React框架本身就是響應用戶狀態改變的事件而執行重新構建用戶界面的工作,這就是典型的響應式編程範式,下面我們總結一下React中響應式原理:

  • 開發者只需關注狀態轉移(數據),當狀態發生變化,React框架會自動根據新的狀態重新構建UI。
  • React框架在接收到用戶狀態改變通知後,會根據當前渲染樹,結合最新的狀態改變,通過Diff算法,計算出樹中變化的部分,然後只更新變化的部分(DOM操作),從而避免整棵樹重構,提高性能。

值得注意的是,在第二步中,狀態變化後React框架並不會立即去計算並渲染DOM樹的變化部分,相反,React會在DOM的基礎上建立一個抽象層,即虛擬DOM樹,對數據和狀態所做的任何改動,都會被自動且高效的同步到虛擬DOM,最後再批量同步到真實DOM中,而不是每次改變都去操作一下DOM。爲什麼不能每次改變都直接去操作DOM樹?這是因爲在瀏覽器中每一次DOM操作都有可能引起瀏覽器的重繪或迴流:

  • 如果DOM只是外觀風格發生變化,如顏色變化,會導致瀏覽器重繪界面。
  • 如果DOM樹的結構發生變化,如尺寸、佈局、節點隱藏等導致,瀏覽器就需要回流(及重新排版佈局)。

React Native

上文已經提到React Native 是React 在原生移動應用平臺的衍生產物,那兩者主要的區別是什麼呢?其實,主要的區別在於虛擬DOM映射的對象是什麼?React中虛擬DOM最終會映射爲瀏覽器DOM樹,而RN中虛擬DOM會通過 JavaScriptCore 映射爲原生控件樹。

JavaScriptCore 是一個JavaScript解釋器,它在React Native中主要有兩個作用:

  1. 爲JavaScript提供運行環境。
  2. 是JavaScript與原生應用之間通信的橋樑,作用和JsBridge一樣,事實上,在iOS中,很多JsBridge的實現都是基於 JavaScriptCore 。

而RN中將虛擬DOM映射爲原生控件的過程中分兩步:

  1. 佈局消息傳遞; 將虛擬DOM佈局信息傳遞給原生;
  2. 原生根據佈局信息通過對應的原生控件渲染控件樹;

至此,React Native 便實現了跨平臺。 相對於混合應用,由於React Native是原生控件渲染,所以性能會比混合應用中H5好很多,同時React Native使用了Web開發技術棧,也只需維護一份代碼,同樣是跨平臺框架。

Weex

Weex 是阿里巴巴於2016年發佈的跨平臺移動端開發框架,思想及原理和React Native類似,最大的不同是語法層面,Weex支持Vue語法和Rax語法,Rax 的 DSL(Domain Specific Language) 語法是基於 React JSX 語法而創造。與 React 不同,在 Rax 中 JSX 是必選的,它不支持通過其它方式創建組件,所以學習 JSX 是使用 Rax 的必要基礎。而React Native只支持JSX語法。

快應用

快應用是華爲、小米、OPPO、魅族等國內9大主流手機廠商共同制定的輕量級應用標準,目標直指微信小程序。它也是採用JavaScript語言開發,原生控件渲染,與React Native和Weex相比主要有兩點不同:

  1. 快應用自身不支持Vue或React語法,其採用原生JavaScript開發,其開發框架和微信小程序很像,值得一提的是小程序目前已經可以使用Vue語法開發(mpvue),從原理上來講,Vue的語法也可以移植到快應用上。
  2. React Native和Weex的渲染/排版引擎是集成到框架中的,每一個APP都需要打包一份,安裝包體積較大;而快應用渲染/排版引擎是集成到ROM中的,應用中無需打包,安裝包體積小,正因如此,快應用才能在保證性能的同時做到快速分發。

總結

優點:

  1. 採用Web開發技術棧,社區龐大、上手快、開發成本相對較低。
  2. 原生渲染,性能相比H5提高很多。
  3. 動態化較好,支持熱更新。

缺點:

  1. 渲染時需要J avaScript 和原生之間通信,在有些場景如拖動可能會因爲通信頻繁導致卡頓。
  2. JavaScript爲腳本語言,執行時需要JIT(Just In Time),執行效率和AOT(Ahead Of Time)代碼仍有差距。
  3. 由於渲染依賴原生控件,不同平臺的控件需要單獨維護,並且當系統更新時,社區控件可能會滯後;除此之外,其控件系統也會受到原生UI系統限制,例如,在Android中,手勢衝突消歧規則是固定的,這在使用不同人寫的控件嵌套時,手勢衝突問題將會變得非常棘手。

自繪UI 與 原生

通過在不同平臺實現一個統一接口的渲染引擎來繪製UI,而不依賴系統原生控件,所以可以做到不同平臺UI的一致性。注意,自繪引擎解決的是UI的跨平臺問題,如果涉及其它系統能力調用,依然要涉及原生開發。

QT

Qt是一個1991年由Qt Company開發的跨平臺C++圖形用戶界面應用程序開發框架。

Flutter

Flutter是Google發佈的一個用於創建跨平臺、高性能移動應用的框架。Flutter和QT mobile一樣,都沒有使用原生控件,相反都實現了一個自繪引擎,使用自身的佈局、繪製系統。

總結

優點:

  • 性能高;由於自繪引擎是直接調用系統API來繪製UI,所以性能和原生控件接近。
  • 靈活、組件庫易維護、UI外觀保真度和一致性高;由於UI渲染不依賴原生控件,也就不需要根據不同平臺的控件單獨維護一套組件庫,所以代碼容易維護。由於組件庫是同一套代碼、同一個渲染引擎,所以在不同平臺,組件顯示外觀可以做到高保真和高一致性;另外,由於不依賴原生控件,也就不會受原生布局系統的限制,這樣佈局系統會非常靈活。

缺點:

  • 動態性不足;爲了保證UI繪製性能,自繪UI系統一般都會採用AOT模式編譯其發佈包,所以應用發佈後,不能像Hybrid和RN那些使用JavaScript(JIT)作爲開發語言的框架那樣動態下發代碼。
  • 開發效率低:QT使用C++作爲其開發語言,而編程效率是直接會影響APP開發效率的,C++作爲一門靜態語言,在UI開發方面靈活性不及JavaScript這樣的動態語言,另外,C++需要開發者手動去管理內存分配,沒有JavaScript及Java中垃圾回收(GC)的機制。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章