歡迎光臨
每天分享高質量文章

愛奇藝 Flutter 跨平臺 Hybrid 實踐

愛奇藝開播助手

愛奇藝開播助手專案,又稱”直播機”,該專案標的是通過一個移動平臺為主播提供多樣化的直播內容。現階段所涵蓋的直播內容包括:游戲直播,美女攝像直播,小劇場直播,其中游戲直播相對主播數量最多,3種推流樣式所涉及的推流SDK基本一致,推流邏輯存在部分差異。

 

該專案的Android端和iOS端架構類似,主要由APP、SDK和so三層構成,APP層負責界面展示和交互,由各端Native代碼實現,so層負責封裝核心的推流、播放等功能,由於更接近底層硬體,使用C實現,而中間的SDK層負責呼叫這些so庫的功能。

 

由於雙端的業務幾乎完全一樣,雙端為了提高代碼的復用率,我們試圖接入一套跨平臺的框架同時開發兩端的APP。

 

為什麼選擇Flutter

移動端跨平臺一直是開發者老生常談的話題,為了盡可能的增加代碼復用,降低開發成本,各大科技巨頭都有自己的跨平臺框架,比如Facebook的React-Native、阿裡的Weex、Cordova等。這些跨平臺框架各有優劣,Google也“不甘寂寞”,在2018年Google開發者大會上重點介紹了自己的跨平臺框架Flutter。

 

和RN和Weex將javascript轉化為原生控制元件渲染不同,Flutter完全掙脫了原生控制元件的“束縛”,如圖1所示,Flutter使用了分層架構,分為Framework和Engine兩個部分,其中Framework層提供各種基礎組件庫,包括各種Widget,動畫等,Engine層則完全由C和C++實現,使用Skia進行渲染(對!就是chrome用的那個圖形渲染框架),官方宣稱可以達到原生app的渲染性能。

 

下圖是和RN、Weex之間的對比:

 

可以看到目前Flutter從各個方面都已經不遜於前兩位,而且在Google新操作系統Fuchsia(被認為是Android的繼任者)也使用Flutter作為其UI框架,今後的發展不可限量。

 

 

除了渲染性能之外,Flutter還有一個非常誘人的特性:HotReload,在debug下的Flutter工程可以快速熱多載到真機上,修改完代碼後Ctrl+S就能實時展現在真機界面上,不需要重新安裝apk包,想想就興奮!

 

如果你對HotReload原理感興趣,可以移步Flutter官網進一步瞭解 HotReload

 

 

總體來看,Flutter有性能好、開發效率高、跨平臺和可無縫接入原有工程等優勢,所以我們嘗試使用Flutter進行開播助手的改造實踐。

開播助手Android端接入

下麵詳細介紹一下Android和iOS是如何接入的。

 

在Android中添加Flutter組件

 

目前開播助手中使用了Flutter的Fragment和View兩種方式,如下麵兩段代碼所示:


使用Flutter.createFragment()和Flutter.createView()兩個方法,這兩個方法可以傳回Flutter創建的供Android使用的Fragment和View,接下來和原生的Fragment和View使用方法就是一模一樣了。(是不是很簡單!)

 

  • 使用Flutter Fragment

 

Flutter.createFragment("settings")
  • 使用Flutter View

 

Flutter.createView(getActivity(), getLifecycle(), "settings");

當然為了告訴Flutter需要使用哪個界面,使用了路由的機制,創建fragment或view的時候需要傳入一個路由的字串,在Flutter工程中也需要使用此字串,代碼如下:

 

void main() { runApp(_widgetForRoute(window.defaultRouteName));}

 

Widget _widgetForRoute(String route) {
  switch (route) {case 'settings':return MaterialApp(home: 
  SettingsPage()); .... }}

 

在Flutter工程的入口處匹配傳入的字串,來決定實體化哪個頁面傳回。

 

使用Module接入

 

開發過程中我們可以使用Moudle依賴來接入,只需要在setting.gradle中添加以下代碼即可:

 

setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir.parentFile,'flutter_liveshow/.android/include_flutter.groovy'))

使用aar接入

 

Android使用aar接入Flutter十分的簡單,只用下麵兩步就可以順利的將使用Flutter開發的界面接入原生的工程。

 

使用gradle工具打aar資源包

 

如果要Android可以使用Flutter的工程,可以將Flutter工程打成aar的包,如下圖所示,進入工程中的.android/目錄,使用./gradlew Flutter:assembleRelease即可。

 

將aar包加入工程並依賴

 

如下圖所示,首先將打好的release包放入libs目錄下

 

目前最新版本的Flutter在集成時需要將sdk中的icudtl.dat檔案放入資源目錄中一起打包,否則會出錯,官方正在修複此問題,相信不久就能解決。

開播助手iOS端接入

Podfile接入Flutter

 

flutter_application_path = '../flutter_liveshow/'
eval(File.read(File.join(flutter_application_path, '.ios''Flutter''podhelper.rb')), binding)

eval(string [, binding [, filename [,lineno]]]) → obj
Evaluates the Ruby expression(s) in string. If binding is given, which must be a Binding object, the evaluation is performed in its context. If the optional filename and lineno parameters are present, they will be used when reporting syntax errors.

添加完成後執行pod install。這段代碼實際就是在Podfile中加入一段Flutter
所需要的腳本。如果基於Flutter master channel開發,生成的podhelper.rb中會增加post_install hooks,如果專案中也使用該hooks,需要手動合併。所幸這個檔案只有在修改Flutter plugin依賴並運行Flutter package get之後才會重新生成。

 

Dart代碼編譯設置

 

“TARGET APP -> Build Phases -> New Run Script Phase” 新增script phase填入下方代碼

 

"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed

“Build Settings -> Add User-Defined Setting” 新增 FLUTTER_ROOT 欄位。

 

接入Host App

 

  • AppDelegate.swift

 

import Flutter
import FlutterPluginRegistrant // Only if you have Flutter Plugins.

@UIApplicationMainclass AppDelegate: FlutterAppDelegate {
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        GeneratedPluginRegistrant.register(with: self);
        ......}
  • 在App中接入Flutter開發的頁面

 

let flutterViewController = FlutterViewController()
flutterViewController.setInitialRoute("settings")
navigationController?.pushViewController(flutterViewController, animated: true)

實際效果和今後的計劃

目前已經接入了使用Flutter開發的設置頁面和搜索節目單結果界面,具體兩端的效果如下圖所示:

 

 iOS

 Android

經過實際接入發現使用Flutter開發的界面的流暢度和原生開發的界面幾乎沒有區別,可以說是完全無縫的體驗,使用Flutter開發部分獨立性較強的頁面還是沒有任何問題的。


Flutter目前還處於推廣階段,考慮到其各種優秀的特性,以後一定會發展的越來越好。開播助手後面還準備將更多頁面接入Flutter,先從部分串列頁開始,並且維護一個Flutter的組件庫,供今後頁面開發使用,提高兩端代碼復用率,逐步實現一套代碼雙端運行的目的。

    赞(0)

    分享創造快樂