编写手机App,用什么语言?
创新互联建站主要从事成都网站建设、网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务东兴,10余年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:13518219792
从简单到复杂,可以分三级:
简单方案:HTML5
其实就是把网页封装成App。编程语言就是网页三件套:HTML+CSS+Javascript
有多种工具和框架,如Cordova, uni等等。
这种方式实现“App”最容易,且跨平台,对于iOS和Android做一套就行了。代价是功能弱,性能低,换句话说就是“卡”。
中等方案:原生跨平台框架
这类方案在iOS和Android之上自行实现一套原生框架。通用的Flutter, ReactNative都是流行的原生跨平台框架。适用于 游戏 的Cocos2D,Corona SDK也可以算在这一级里。
这类方案实现App难度中等,因为跨平台,一次开发,iOS和Android都能运行。功能和性能也是中等,比不上原生App,但比HTML5的又好很多。
复杂方案:原生开发
直接在iOS和Android上各自开发一套原生App。
iOS可以使用Objective C或Swift。
Android可以使用Java或Kotlin。
还是来一个图表吧,虽然简单,却很明了:
推荐用Flutter,简单。
以前自己用android原生写过7天酒店签到程序,不过当时的安卓还是比较难写的,不像现在越来越容易上手。
Flutter
Flutter是一个由谷歌开发的开源移动应用软件开发工具包,用于为Android、iOS、 Windows、Mac、Linux、Google Fuchsia开发应用。
Flutter应用是使用Dart语言编写的,虽然是新的一种语言,但是难度不算大,上网搜下相关教程学习下,应该就能很快上手。
Flutter效果
这里是我上个月仿照教程弄的一个简单APP,效果图如下:
点击"Next"就切换下一张,点击"Pre"就切换前一张,点击“Reset”就全部滑落下来。
我女儿最喜欢中间的Reset效果,哈哈。
希望这个答案能帮到你。
现在Flutter正式版已经出来了,原生性能,安卓iOS多平台支持,谷歌大厂背书,大家可以比较放心的学习。编程语言用的是Dart,可以看做是加了语法糖版本的Java,学习起来也比较容易,如果想做手机app,可以考虑使用它。
如果只是自己做着玩的话推荐用H5开发,开发工具HBuilder或者HBuilderX。
先科普下什么是IOS和Android吧。
IOS只是操作系统而已,是苹果的操作系统。
开发IOS上运行的APP的话,现在流行的语言是Object-C和Swift。
Android也是操作系统,是谷歌基于Linux内核开发出来的手机操作系统。
开发Android上运行的APP的话,现在流行的语言我觉得仍然还是JAVA。
如果想要真的做一款APP的话,不仅仅会一门语言就够了,涉及的东西比较多,如下是我给你的学习推荐路线。
学习路线:
1:先学习js,然后学习下html 、css。
学习这些可以上菜鸟教程或者W3School网站学习。
开发工具使用vscode或者Notepad++都可以的。
2:了解Mui常用组件(官网:),
熟悉常用API(官网:)。
3:服务端的开发,要么用java开发,要么用.net webapi开发,推荐理由,java目前是主流,.net webapi简单容易。
java 开发工具IntelliJ IDEA,.net 开发工具 vs。
4:数据存储使用mysql。
补充说明:如果是想做专业开发APP的话还是建议用java开发客户端,ios APP则用swift开发。
当然现在为了一套代码多个平台,使用H5开发专业APP的也有。
会了就可以正式撸代码实现自己简单的APP了。
回答完毕,谢谢。我是只说代码的大饼。
那当然首选是h5套壳了。关于语言方面,我建议还是用PHP吧。随着进一步学习,可以学习uinapp一键多端。H5、小程序、App、小程序支持多个平台上架、微信抖音支付宝百度,希望可以帮助你
目前有三种app开发方式:原生app、混合app、webapp。
原生app:安卓需要java语言,ios需要 objec t-c,wp需要的.net语言。这种app用户体验最好,性能也是最好的,开发成本高,开发周期长,一款app需要开发多个语言版本;
混合app:需要h5,javascript,了解每个混合框架,比如appcan、hbulider、phonegap等等,以及封装的中间件。这种开发方式的用户体验、性能没有原生的好,但是他的开发周期短,开发成本低,对开发人员技能掌握比较高,开发一套程序可以兼容到多个设备上;
webapp:需要h5、javascript语言,不能调用底层设备,用户体验效果次之,开发简单,开发成本低,开发周期短,可以兼容多个设备。
综上所述三种开发各有优缺点,要根据具体的项目需求来选择适合自己的开发语言和开发场景。
uniapp了解下,多端应用。app的话要考虑安卓和苹果,但学了二种学习成本比较高。用uniapp就解决了。
现在中小型企业都在逐渐采用跨平台开发的模式 效率高 成本低 作为个人更是开发不二的选择 你问的iOS和安卓是原生开发 需要不同的开发语言和框架 学习成本也很高 既然你说你是小白 如果采用原生开发 可能得大概花一年半载才能开始上手
采用跨平台开发 只需要学习一下html css JavaScript 然后选择跨平台开发框架 比如react flutter uniapp 都可以 跨平台就是指你这一套代码编写的app可以到不同平台运行 比如iOS安卓都OK 但其实很多还可以编译到各类小程序平台运行 所以很方便
我这里推荐uniapp 一个基于vue的跨端开发框架 我自己也用这个开发了很多项目 确实很快 也提供了原生渲染能力 不做 游戏 等软件 基本没啥问题 社区插件市场也很热闹 基本有问题可以很快解决 希望可以帮到你。
按照开发方式可分为原生开发、混合开发、webapp开发,不同的开发方式学习的编程语言不一样,下面我们来一个一个分析一下:
一、原生开发
原生开发的编程语言主要为针对IOS运行环境的为编程语言为Swift或Object c,安卓环境为Java或Kotlin,WP环境为NET。原生开发的运行效率最高,用户体验最好,但是需要学习不同平台的编程语言,学习门槛较高。
二、混合开发(伪原生开发)
混合开发技术主要采用一套特别的渲染引擎来渲染UI界面和交互,按照渲染引擎可分为html与dart,其编程语言主要是Javascript或Typescript、Dart。
目前基于html渲染的开发框架有react native、weex、uniapp,基于dart的开发框架只有flutter。
混合开发由于调用了原生的控件来渲染UI,所以加载和体验与原生差不多,学习成本比较低,只要会js,选择一个框架开发就行了,或者学习dart语言,进行flutter开发。
三、webapp开发
webapp开发主要利用原生环境中的浏览器控件来装载服务器上的html页面,实际这个app就是一个自定义的浏览器app,所以只要会html,就会开发webapp,由于app内部加载的是远程的网页,所以加载速度和体验最差。
以上是我个人的总结,有不对的欢迎指出,谢谢。
本人用c#,除了单片机用c,cad CATIA,多媒体主要Adobe,它干完所有,不需要性能的视图混合dom代码。
这一周继续聊跨平台桌面开发这个事情。
在这篇文章中,我暂时会放下Electron与WebView2的一个对比,而聊一聊跨平台这个对于程序员群体来说不陌生的词。
一个趋势是:跨平台开发几乎是在各个技术方向都会持续发展的
跨平台这个词,对于程序员来说,应该是不陌生的。因为这个概念不只在某一端存在,后端,前端,移动端,桌面端几乎所有方向都对跨平台有需求。
在后端,Java是跨平台的,当你用Java来编写后端服务时,并不需要考虑操作系统,因为它几乎支持主流的操作系统。现在,编写一个后端服务,选用Java仍是主流。虽然可能它的跨平台特性已经不是程序员最在意的点了。
而在移动端,类似React Native,Flutter也是非常有名的跨平台移动开发,它们与移动原生开发方式之间一直是竞争与共存。
而前端因为依托于浏览器,天然就是跨平台的。事实上,很多应用或服务早期纷纷选择从原生应用迁移至前端WEB方式的一个非常重要的原因就在于它是跨平台的。
桌面操作系统很长一段时间一直是Windows一家独大,所以桌面开发一直是Windows独占,直至现在为止,很多专业级的软件仍然是Windows独占的。
而Linux桌面操作系统与MacOS桌面操作系统,早些年几乎可以忽略不计,压根不需要考虑这两种系统。但随着近些年它们的慢慢流行,特别是苹果的MacOS的以其杰出的工艺,流畅的体验,叠加苹果手机的流行,其市场份额增长非常之快,在特定的诸如编程,设计等行业人群中使用范围较广,这使得开发支持MacOS系统这个点变得越来越重要。
所以,在桌面开发领域,跨平台的需求也越来越高。
这也是Electron及早期的NW.js能迅速发展起来并得到非常广应用的原因所在。
无论是哪一端,跨平台技术之所以频繁出现与不断发展,其根本原因就在于编程的一个重要痛点在于:
为了让同一个服务能在所有设备上运行,程序员不得不编写与维护非常多不同版本的程序
每一个程序或软件后面的服务,都有一个非常迫切的需求,就是期望它的用户无论何时,无论何地,无论使用任何设备,都能方便友好的使用这个服务。
也是因为这个原因,Web发展起来了,因为Web的优势就在这,只要你的设备上有浏览器,就能访问。
但Web毕竟性能有限,且浏览器这种形式并不利于用户忠诚度的培养,它存在天然的弱点。一些简单的操作服务使用Web并无问题,但稍微有点要求的,Web可能就并不是非常适合。
所以,一种趋势不可避免地流行起来:
对不同设备或系统进行抽象,基于某一种特定的编程语言,编写出能与原生程序相媲美的,又能跨平台的技术便层出不穷了
对吧,Java是使用JVM来抽象不同的操作系统,React Native则是使用虚拟DOM以及转换成原生控件的方式来实现跨平台,而Electron则是通过性能较好的Chrome内核+NodeJS原生调用能力的搭配来实现跨平台桌面开发。
总而言之,这种跨平台的技术不会消亡,只会有新的技术层出不穷,而它们与原生开发一定是相互竞争,配合与共存的。相互之间无法取代。
那再回到跨平台技术上来说,一个良好的跨平台开发的技术或框架,重点是什么。
或者换种方式说,哪些特性使得它更易于流行起来?
我个人认为有以下的几个点:
跨平台开发技术能不能流行起来的一个非常重要的点就在于,使用了什么样的编程语言。
以移动端跨平台开发技术来说明,一个React Native,一个Flutter,这两个是比较知名主流的跨平台移动开发技术。React Native使用的是前端React技术,而Flutter则是Google的D语言。
显而易见的是,虽然Flutter是使用skia引擎在底层重绘一套UI,其性能相比React Native这种模式更佳,但React Native更易于被接受。
在流行度上,React Native始终比Flutter更流行,一个最重要的原因也在于:
使用已熟知的前端编程语言,比起重新学习一个D语言更易于被接受,维护成本更可控。
这个问题在跨平台桌面开发中也是类似,跨平台桌面开发技术也不是Electron最开始出现,比如著名的QT很早就有了,但比起Electron这种使用前端编程技术来说,显然在编程语言的门槛上和程序员群体上都存在困难,这也是Electron能后来居上的原因所在。
因为,大多数程序员群体,相比较另外学习一门什么语言去做什么,使用自己熟悉的语言来做什么是更容易,意愿也更高。
而从公司或团队的考量上看,选择偏门的小众语言存在成本上的顾虑,比如人员招聘是否容易?
跨平台技术在尝试解决不同平台不一致,它或多或少会损耗性能。这也决定了几乎没有任何一个跨平台技术能取代原生开发。
这是一个取舍的问题,对于一个程序来说,究竟性能有多重要。对于比较看重性能的程序来说,原生开发可能是最优选择。
但跨平台的性能损耗也有高低之分,并不在同一水平线上。
其实,无论是Electron,或是WebView2,都是基于浏览器内核+前端技术的跨平台桌面解决方案,这也是为什么要把它们放在一起聊的原因。
Electron是先行者(当然,严格说来,NW.js出现的更早,但今天它的流行度已远远落后于Electron了),而WebView2则是后来者。
那做为后来者的WebView2究竟做了哪些改进?它又有多大的能力来挑战Electron呢?
下一篇,继续聊。
前言
为什么跨平台是发展趋势?
同一个应用,各个“端”独立开发,不仅开发周期长,而且人员成本高。同时,作为技术人员,也不应该满足于这种重复、低能的工作状态。在这样的形势下,跨平台的技术方案也受到越来越多人和企业的关注。
本篇文章我将从原理、优缺点等方面为大家分享跨平台技术
一. H5
说到跨平台,没人不知道H5。不管是在Mac、Windows、Linux、iOS、Android还是其他平台,只要给一个浏览器,连“月球”上它都能跑。
1.浏览器架构
下面,我们来看看让H5如此横行霸道的浏览器的架构:
浏览器由以上7个部分组成,而“渲染引擎”是性能优化的重中之重,一起了解其中的渲染原理。
2.渲染引擎原理
不同的浏览器内核不同,渲染过程会不太一样,但主要流程还是一致的。
分为下面6步骤:
从以上6步,我们可以总结渲染优化的要点:
以上就是浏览器端的内容。但H5作为跨平台技术的载体,是如何与不同平台的App进行交互的呢?这时候JSBridge就该出场了。
3.JSBridge原理
JSBridge,顾名思义,是JS和Native之间的桥梁,用来进行JS和Native之间的通信。
通信分为以下两个维度:
那么App内加载H5的过程是什么样的呢?
4.App打开H5过程
打开H5分为4个阶段:
这四步,对应的过程如上图所以,我们可以针对性的做性能优化。
5.优缺点分析
下面,我们进行H5的优缺点分析:
优点
缺点
虽然H5目前还存在不足,但随着PWA、WebAssembly等技术的进步,相信H5在未来能够得到越来也好的发展。
二.小程序
2018年是微信小程序飞速发展的一年,19年,各大厂商快速跟进,已经有了很大的影响力。下面,我们以微信小程序为例,分析小程序的技术架构。
小程序跟H5一样,也是基于Webview实现。但它包含View视图层、App Service逻辑层两部分,分别独立运行在各自的WebView线程中。
1.View
可以理解为h5的页面,提供UI渲染。由WAWebview.js来提供底层的功能,具体如下:
每个窗口都有一个独立的WebView进程,因此微信限制不能打开超过5个层级的页面来保障用户体验。
2. App Service
提供逻辑处理、数据请求、接口调用。由WAService.js来提供底层的功能,具体如下:
运行环境:
仅有一个WebView进程
3.View App Service通信
视图层和逻辑层通过系统层的JSBridage进行通信,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层将触发的事件通知到逻辑层进行业务处理。
4. 优缺点分析
优点
缺点
既然WebView性能不佳,那有没有更好的方案呢?下面我们看看React Native。
三.React Native
RN的理念是在不同平台上编写基于React的代码,实现Learn once, write anywhere。
Virtual DOM在内存中,可以通过不同的渲染引擎生成不同平台下的UI,JS和Native之间通过Bridge通信
1.React Native 工作原理
在 React 框架中,JSX 源码通过 React 框架最终渲染到了浏览器的真实 DOM 中,而在 React Native 框架中,JSX 源码通过 React Native 框架编译后,与Native原生的UI组件进行映射,用原生代替DOM元素来渲染,在UI渲染上非常接近Native App。
2.React Native 与Native平台通信
3.优缺点分析
优点
缺点
4.RN展望
虽然RN还存在不足,但RN新版本已经做了如下改进,并且RN团队也在积极准备大版本重构,能否成为开发者们所信赖的跨平台方案,让我们拭目以待。
既然React Native在渲染方面还摆脱不了原生,那有没有一种方案是直接操控GPU,自制引擎渲染呢,我们终于迎来了Flutter!
四.Flutter
Flutter是Google开发的一套全新的跨平台、开源UI框架,支持iOS、Android系统开发,并且是未来新操作系统Fuchsia的默认开发套件。渲染引擎依靠跨平台的Skia图形库来实现,依赖系统的只有图形绘制相关的接口,可以在最大程度上保证不同平台、不同设备的体验一致性,逻辑处理使用支持AOT的Dart语言,执行效率也比JavaScript高得多。
1.Flutter架构原理
2.Dart优势
很多人会好奇,为什么Flutter要用Dart,而不是用JavaScript开发,这里列下Dart的优势
3.优缺点分析
优点
缺点
趋势一:更加移动优先
响应式设计显然是目前Web前端开发领域的主要趋势之一,并且这一趋势在未来还将持续一段时间。虽然现在的响应式设计大部分还是以PC版优先,然而如果有一天我们把PC版放到比移动版次要的位置上,也没有什么好奇怪的。因为,目前许多Web前端开发者已经开始转向以移动优先方案来做他们的响应式设计和开发,这就象征着一个重大转变,值得我们跟进的。
趋势二:更多使用快速原型开发工具
众多Web前端开发者从2016年开始尝试使用快速原型开发工具,而在2018年将是这种技术真正爆发的一年。“UXpin、Webflow、Invision以及其它许多快速原型开发工具,让设计师不用写一行代码,就能为网站和服务快速创建低保真和高保真原型,便于设计师衡量它们的可用性和美观性。” Web设计师Jamie Leeson says如是说,“许多工具也允许你在浏览器中设计原型并从工具里真正启动网站自身。”
不管未来前端发展方向如何,可以肯定的是未来前端人才需求依旧很大。想学前端开发专业的机构也很多,你可以去线下试听课程了解一下,例如北大青鸟、南京中博软件学院、南京课工场等等都有试听课程的!
编程语言是程序员(开发人员)用来与计算机进行通信的计算机语言。它是用任何特定语言(C、C++、Java、Python)编写的一组指令,用于执行特定任务。编程语言主要用于开发桌面应用程序、网站和移动应用程序。以下是 2022 年最流行的顶级语言。
Python
Python 是由 Guido van Rossum 于 1980 年代后期在荷兰构建的。Python 最初是作为 Java 在行业中的竞争对手而构建的,后来逐渐流行起来。目前,Python 在研究人员和开发人员社区中都非常受欢迎。Python 在 IEEE Spectrum 的语言排名中名列前茅,得分为满分 100。此外,Python 也很受尊重,支持率高达 44.1%。
Python 几乎适用于任何事物。Django 和 Flask 可用于 Web 开发,而 Jupyter 和 Spyder 等科学工具则用于分析和研究目的。如果您喜欢自动化,Selenium 可以帮助您!该语言的灵活性使 Python 几乎可以在任何地方使用。到目前为止,这些是 Python 中比较流行的产品。Python 的巨大支持基础(仅次于 JavaScript)产生了大量使用该语言的包、框架,甚至是成熟的开源软件。
总的来说,Python 可能对数据科学和机器学习有最大的支持。虽然还有其他语言(如 R 和 MATLAB)提供竞争,但 Python 是数据科学领域的严格统治者。机器学习中使用的大多数框架和库都仅用 Python 编写,如果想要学习机器学习(或一般的数据科学),它可能是最好的语言。
JavaScript
JavaScript 在这一点上几乎是行业领导者。JavaScript 最初于 1994 年作为 Netscape Navigator(当时最好的浏览器之一)的脚本语言而构建,它迅速崛起。直到 2008 年,Google 才在为 Google Chrome 构建 V8 引擎时设计了现代 JavaScript。最初由 Netscape 构建为 Java 的竞争对手,JavaScript 现在在开发领域拥有自己的空间。JavaScript 因其流行而被广泛认为是“互联网语言”。JavaScript 在开发者社区中的支持率最高——高达 67.7%。一般来说,JavaScript 适用于任何类型的开发活动,如移动应用程序开发、Web 开发、桌面应用程序开发等。
JavaScript 有各种各样的库和框架,可以在开发过程中使用。有用于前端开发的 Angular、Vue 和 React,而 Node.js 是一种用于后端开发的非常灵活的语言。Jest 和 Mocha 是两个灵活的工具,可帮助设置单元测试以检查功能是否按预期工作。当然,如果您对其中任何一个都不太满意,您可以在前端使用普通的 HTML、CSS 和 JavaScript——就这么简单!由于来自世界各地开发人员的巨大支持,JavaScript 拥有任何语言都可以夸耀的最多数量的支持包。尽管如此,人们继续构建越来越多的包,以增加使用该语言的便利性。
Java
Java 由 James Gosling、Mike Sheridan 和 Patrick Naughton 于 1991 年构建为“Oak”语言,是第一种在全球产生重大影响的语言。虽然新的编程语言使用与 C/C++ 相同的格式,但它融入了某些新思想,使其对更多人更具吸引力。Java 运行的原则是“一次编写,随处运行”——这意味着具有不同硬件和操作系统配置的系统可以轻松运行 Java 程序。
Java 也有各种各样的库和框架,它们在底层使用 Java。Java 用于通过 Spring 和 Hibernate 进行应用程序开发。JUnit 帮助我们为 Java 项目设置单元测试。最重要的是,Java 被用于开发原生 Android 应用程序(Android SDK 本身由 Java 开发工具包或 JDK 提供支持)。Java 可能是大多数人在大学或学校的计算机编程入门课程中被介绍的语言。Java 是用于向大众教授面向对象编程的语言。
Java 在分析和研究领域也备受推崇。Java 唯一的问题是目前该语言的支持包和项目很少。很少有社区参与——这是大多数主流语言都有的。尽管如此,Java 是一种非常容易掌握和学习的语言——这在一定程度上解释了该语言的吸引力。但是,要掌握某种形式的语言确实需要一些时间。
C++
也许人们在本文中可以期待的最令人震惊的答案之一是 C++。尽管是大多数人用来学习数据结构和算法概念的语言,但该语言本身在实际世界中却很少使用。C++ 最初由 Bjarne Stroustrup 于 1982 年创建,作为 C 编程语言的扩展,在接下来的几年中继续声名鹊起。
C++ 可用于分析、研究以及 游戏 内开发。流行的 游戏 开发引擎——虚幻引擎——使用 C++ 作为脚本语言,用于构建 游戏 时可以定义的所有功能。C++ 在软件开发中也有广泛的用途。介于面向对象方法和面向方法方法之间,C++ 可以灵活地使用它生成的软件的性质。在 TIOBE 指数中排名第 4 意味着 C++ 至今仍具有吸引力。C++也广泛用于系统软件开发,比其他语言更容易理解。在操作系统等敏感领域使用 C++ 的主要原因是 C++ 程序的编译时间非常短。
C++ 可能拥有所有语言中最大的学习社区。大多数学生会开始他们的算法课程,用 C++ 构建树、链表、堆栈、队列和许多其他数据结构。当然,只要注意细节,它就很容易上手和学习,也很容易掌握。
Typescript
TypeScript 是 JavaScript 的超集,具有与 JavaScript 几乎相同的应用程序。TypeScript 可用于 Web 开发、移动应用程序开发、桌面应用程序开发等。在 StackOverflow 的最受欢迎语言列表中,TypeScript 是第二受欢迎的语言,受到 67.1% 的开发人员的喜爱(仅次于 Rust)。
TypeScript 主要是一种用于开发的语言,因此它对科学界没有太大吸引力。但是,由于 TypeScript 的新功能,可以预期它可能会激发更大程度的研究兴趣。该语言的技能上限比 JavaScript 低得多——并且 JavaScript 的许多“难以理解”的行为已在 TypeScript 中得到简化。换句话说,您将头撞到墙上的机会略小。
Golang
新语言正在迅速崛起,新的竞争者即将挑战 JavaScript 和 Python 拥有的宝座。由谷歌(两者的名字中都有“Go”!)主要是为了推进函数式编程的事业,Golang 在短时间内建立了大量的追随者。Golang 已经成为 StackOverflow 第五大最适合学习的语言,受到 62.3% 的开发人员的喜爱。
Golang 用于多个领域,用于开发强大的软件以及用于 Web 和移动应用程序的后端。目前,Golang 甚至支持一些基本的 Web 开发。虽然它仍处于取代 JavaScript 作为网络语言的阶段,但它正在迅速成为支持下一阶段网络的语言。
Golang 比此列表中的其他语言更难学习。此外,Golang 是一种开源语言,每次重大更新都会频繁更改,因此保持更新是必要的。
Dart
Dart 是工业领域发展最快的语言之一。谷歌在语言领域的贡献显着增加,以与微软的 TypeScript 日益流行的竞争相抗衡。Dart 因其简单性而受到世界各地程序员的高度喜爱。
Dart 用于多平台应用程序开发。与 JavaScript 一样,Dart 用于构建任何人都可以使用电子设备运行的软件。目前 Dart 最著名的用途是 Flutter 框架,Flutter 是一种用于移动应用程序开发的语言。最近的谷歌趋势表明,Flutter 尽管是一个较新的框架,但比 React Native 更受欢迎,后者是业界已经建立的移动应用程序开发框架。
Dart 比 JavaScript 更容易学习,并且能够很好地简化甚至难以理解的案例。随着市场上的 TypeScript 和 Dart 的出现,程序员在选择一种他们真正想要学习的语言时会面临多种选择。
文/陈炉军
整理/LiveVideoStack
大家好,我是阿里巴巴闲鱼事业部的陈炉军,本次分享的主题是Flutter浪潮下的音视频研发探索,主要内容是针对闲鱼APP在当下流行的跨平台框架Flutter的大规模实践,介绍其在音视频领域碰到的一些困难以及解决方案。
分享内容主要分为四个方面,首先会对Flutter有一个简单介绍以及选择Flutter作为跨平台框架的原因,其次会介绍Flutter中与音视频关系非常大的外接纹理概念,以及对它做出的一些优化。之后会对闲鱼在音视频实践过程中碰到的一些Flutter问题提出了一些解决方案——TPM音视频框架。最后是闲鱼Flutter多媒体开源组件的介绍。
Flutter
Flutter是一个跨平台框架,以往的做法是将音频、视频和网络这些模块都下沉到C++层或者ARM层,在其上封装成一个音视频的SDK,供UI层的PC、iOS和Android调用。
而Flutter做为一个UI层的跨平台框架,顾名思义就是在UI层也实现了一个跨平台开发。可以预想的是未Flutter发展的好的话,会逐渐变为一个从底层到UI层的一个全链路的跨平台开发,技术人员分别负责SDK和UI层的开发。
在Flutter之前已经有很多跨平台UI解决方案,那为什么选择Flutter呢?
我们主要考虑性能和跨平台的能力。
以往的跨平台方案比如Weex,ReactNative,Cordova等等因为架构的原因无法满足性能要求,尤其是在音视频这种性能要求几乎苛刻的场景。
而诸如Xamarin等,虽然性能可以和原生App一致,但是大部分逻辑还是需要分平台实现。
我们可以看一下,为什么Flutter可以实现高性能:
原生的native组件渲染以IOS为例,苹果的UIKit通过调用平台自己的绘制框架QuaztCore来实现UI的绘制,图形绘制也是调用底层的API,比如OpenGL、Metal等。
而Flutter也是和原生API逻辑一致,也是通过调用底层的绘制框架层SKIA实现UI层。这样相当于Flutter他自己实现了一套UI框架,提供了一种性能超越原生API的跨平台可能性。
但是我们说一个框架最终性能怎样,其实取决于设计者和开发者。至于现在到底是一个什么状况:
在闲鱼的实践中,我们发现在正常的开发没有特意的去优化UI代码的情况下,在一些低端机上,Flutter界面的流畅性是比Native界面要好的。
虽然现在闲鱼某些场景下会有卡顿闪退等情况,但是这是一个新事物发展过程中的必然问题,我们相信未来性能肯定不会成为限制Flutter发展的瓶颈的。
在闲鱼实践Flutter的过程中,混合栈和音视频是其中比较难解决的两个问题,混合栈是指一个APP在Flutter过程中不可能一口气将所有业务全部重写为Flutter,所以这是一个逐步迭代的过程,这期间原生native界面与Flutter界面共存的状态就称之为混合栈。闲鱼在混合栈上也有一些比较好的输出,例如FlutterBoost。
外接纹理
在讲音视频之前需要简要介绍一下外接纹理的概念,我们将它称之为是Flutter和Frame之间的桥梁。
Flutter渲染一帧屏幕数据首先要做的是,GPU发出的VC信号在Flutter的UI线程,通过AOT编译的机器码结合当前Dart Runtime,生成Layer Tree UI树,Layer Tree上每一个叶子节点都代表了当前屏幕上所需要渲染的每一个元素,包含了这些元素渲染所需要的内容。将Layer Tree抛给GPU线程,在GPU线程内调用Skia去完成整个UI的渲染过程。Layer Tree中有PictureLayer和TextureLayer两个比较重要的节点。PictureLayer主要负责屏幕图片的渲染,Flutter内部实现了一套图片解码逻辑,在IO线程将图片读取或者从网络上拉取之后,通过解码能够在IO线程上加载出纹理,交给GPU线程将图片渲染到屏幕上。但是由于音视频场景下系统API太过繁多,业务场景过于复杂。Flutter没有一套逻辑去实现跨平台的音视频组件,所以说Flutter提出了一种让第三方开发者来实现音视频组件的方式,而这些音视频组件的视频渲染出口,就是TextureLayer。
在整个Layer Tree渲染的过程中,TextureLayer的数据纹理需要由外部第三方开发者来指定,可以把视频数据和播放器数据送到TextureLayer里,由Flutter将这些数据渲染出来。
TextureLayer渲染过程:首先判断Layer是否已经初始化,如果没有就创建一个Texture,然后将Texture Attach到一个SufaceTexture上。
这个SufaceTexture是音视频的native代码可以获取到的对象,通过这个对象创建的Suface,我们可以将视频数据、摄像头数据解码放到Suface中,然后Flutter端通过监听SufaceTexture的数据更新就可以顺利把刚才创建的数据更新到它的纹理中,然后再将纹理交给SKIA渲染到屏幕上。
然而我们如果需要用Flutter实现美颜,滤镜,人脸贴图等等功能,就需要将视频数据读取出来,更新到纹理中,再将GPU纹理经过美颜滤镜处理后生成一个处理后的纹理。按Flutter提供的现有能力,必须先将纹理中的数据从GPU读出到CPU中,生成Bitmap后再写入Surface中,这样在Flutter中才能顺利的更新到视频数据,这样做对系统性能的消耗很大。
通过对Flutter渲染过程分析,我们知道Flutter底层需要渲染的数据就是GPU纹理,而我们经过美颜滤镜处理完成以后的结果也是GPU纹理,如果可以将它直接交给Flutter渲染,那就可以避免GPU-CPU-GPU这样的无用循环。这样的方法是可行的,但是需要一个条件,就是OpenGL上下文共享。
OpenGL
在说上下文之前,得提到一个和上线文息息相关的概念:线程。
Flutter引擎启动后会启动四个线程:
第一个线程是UI线程,这是Flutter自己定义的UI线程,主要负责GPU发出的VSync信号时候用当前Dart编译的机器码和当前运行环境创建出Layer Tree。
还有就是IO线程和GPU线程。和大部分OpenGL处理解决方案中一样,Flutter也采取一个线程责资源加载,一部分负责资源渲染这种思路。
两个线程之间纹理共享有两种方式。一种是EGLImage(IOS是 CVOpenGLESTextureCache)。一种是OpenGL Share Context。Flutter通过Share Context来实现纹理共享,将IO线程的Context和GPU线程的Context进行Share,放到同一个Share Group下面,这样两个线程下资源是互相可见可以共享的。
Platform线程是主线程,Flutter中有一个很奇怪的设定,GPU线程和主线程共用一个Context。并且在主线程也有很多OpenGL 操作。
这样的设计会给音视频开发带来很多问题,后面会详细说。
音视频端美颜处理完成的OpenGL纹理能够让Flutter直接使用的条件就是Flutter的上下文需要和平台音视频相关的OpenGL上下文处在一个Share Group下面。
由于Flutter主线程的Context就是GPU的Context,所以在音视频端主线程中有一些OpenGL操作的话,很有可能使Flutter整个OpenGL被破坏掉。所以需要将所有的OpenGL操作都限制在子线程中。
通过上述这两个条件的处理,我们就可以在没有增加GPU消耗的前提下实现美颜和滤镜等等功能。
TPM
在经过demo验证之后,我们将这个方案应用到闲鱼音视频组件中,但改造过程中发现了一些问题。
上图是摄像头采集数据转换为纹理的一段代码,其中有两个操作:首先是切进程,将后面的OpenGL操作都切到cameraQueue中。然后是设置一次上下文。然后这种限制条件或者说是潜规则往往在开发过程中容易被忽略的。而这个条件一旦忽略后果就是出现一些莫名其妙的诡异问题极难排查。因此我们就希望能抽象出一套框架,由框架本身实现线程的切换、上下文和模块生命周期等的管理,开发者接入框架以后只需要安心实现自己的算法,而不需要关心这些潜规则还有其他一些重复的逻辑操作。
在引入Flutter之前闲鱼的音视频架构与大部分音视频逻辑一样采用分层架构:
1:底层是一些独立模块
2:SDK层是对底层模块的封装
3:最上层是UI层。
引入Flutter之后,通过分析各个模块的使用场景,我们可以得出一个假设或者说是抽象:音视频应用在终端上可以归纳为视频帧解码之后视频数据帧在各个模块之间流动的过程,基于这种假设去做Flutter音视频框架的抽象。
咸鱼Flutter多媒体开源组件
整个Flutter音视频框架抽象分为管线和数据的抽象、模块的抽象、线程统一管理和上下文同一管理四部分。
管线,其实就是视频帧流动的管道。数据,音视频中涉及到的数据包括纹理、Bit Map以及时间戳等。结合现有的应用场景我们定义了管线流通数据以Texture为主数据,同时可以选择性的添加Bit Map等作为辅助数据。这样的数据定义方式,避免重复的创建和销毁纹理带来的性能开销以及多线程访问纹理带来的一些问题。也满足一些特殊模块对特殊数据的需求。同时也设计了纹理池来管理管线中的纹理数据。
模块:如果把管线和数据比喻成血管和血液,那框架音视频的场景就可以比喻成器官,我们根据模块所在管线的位置抽象出采集、处理和输出三个基类。这三个基类里实现了刚才说的线程切换,上下文切换,格式转换等等共同逻辑,各个功能模块通过集成自这些基类,可以避免很多重复劳动。
线程:每一个模块初始化的时候,初始化函数就会去线程管理的模块去获取自己的线程,线程管理模块可以决定给初始化函数分配新的线程或者已经分配过其他模块的线程。
这样有三个好处:
一是可以根据需要去决定一个线程可以挂载多少模块,做到线程间的负载均衡。第二,多线程并发式能够保证模块内的OpenGL操作是在当前线程内而不会跑到主线程去,彻底避免Flutter的OpenGL 环境被破坏。第三,多线程并行可以充分利用CPU多核架构,提升处理速度。
从Flutter端修改Flutter引擎将Context取出后,根据Context创建上下文的统一管理模块,每一个模块在初始化的时候会获取它的线程,获取之后会调用上下文管理模块获取自己的上下文。这样可以保证每一个模块的上下文都是与Flutter的上下文进行Share的,每个模块之间资源都是共享可见的,Flutter和音视频native之间也是互相共享可见的。
基于上述框架如果要实现一个简单的场景,比如画面实时预览和滤镜处理功能,
1:需要选择功能模块,功能模块包括摄像头模块、滤镜处理模块和Flutter画面渲染模块,
2:需要配置模块参数,比如采集分辨率、滤镜参数和前后摄像头设置等,
3:在创建视频管线后使用已配置的参数创建模块
4:最后管线搭载模块,开启管线就可以实现这样简单的功能。
上图为整个功能实现的代码和结构图。
结合上述音视频框架,闲鱼实现了Flutter多媒体开源组件。
组要包含四个基本组件分别是:
1:视频图像拍摄组件
2:播放器组件
3:视频图像编辑组件
4:相册选择组件
现在这些组件正在走内部开源流程。预计9月份,相册和播放器会实现开源。
后续展望和规划
1:实现开头所说的从底层SDK到UI的全链路的跨端开发。目前底层框架层和模块层都是各个平台各自实现,反而是Flutter的UI端进行了跨平台的统一,所以后续会将底层也按照音视频常用做法把逻辑下沉到C++层,尽可能的实现全链路跨平台。
2:第二部分内容为开源共建,闲鱼开源的内容不仅包括拍摄、编辑组件,还包括了很多底层模块,希望有开发者在基于Flutter开发音视频应用时可以充分利用闲鱼开源出的音视频模块能力,搭建APP框架,开发者只要去负责实现特殊需求模块就可以,尽可能的减少重复劳动。