爱奇艺开播助手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

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