愛奇藝開播助手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

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

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

轉載自公衆號“愛奇藝技術產品團隊”:https://mp.weixin.qq.com/s/f4j3_NGxjAjqNmecc5XrjA

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章