GitChat 做者:周猛
原文: 如何更加安全、高效地利用开源项目?
关注微信公众号:「GitChat 技术杂谈」 一本正经的讲技术html
【不要错过文末彩蛋】前端
在平时的开发过程当中,不免会遇到这样那样的难题,或者一些繁琐且不想纯手工完成的功能,对于这些问题,解决的姿式有不少种,能够经过同事间的交流、上网查资料、去官网找文档等,随着开源的推进和完善,寻找合适的开源项目支持,绝对是一个很好的方法。java
现在市面上的开源项目鱼龙混杂,而且有一些项目早已中止更新维护,跑demo的时候,怎么用怎么正确,一放入项目,却发现哪哪都不合适,好比低版本下才能够运行,高版本删去一些方法,再或者与一些新技术的包冲突等,在众多开源项目中,咱们应该以何种姿式去选择最佳方案?且听我慢慢道来。git
PS:目前我主要是作手机客户端开发,如下的例子会举一些平常开发的例子。程序员
“我喜欢苹果,但是你给了我一车香蕉,而后你说你被本身感动了,问我为何不感动。我无言以对,而后你告诉全世界,你花光了全部的钱给我买了一车香蕉,但是我却没有一点点感动,我必定是一个铁石心肠的人!个人人品肯定是有问题的!我只是喜欢苹果而已啊”。github
对于这样的问题,在咱们的开发过程当中也常常遇到,产品经理只是想要一个苹果,而咱们却给他送来了一大包香蕉,后来发现哪哪不合适,又去和产品经理肯定需求,才发现本身想的是错的,相信这样的例子,在每一个人身边都有过,由于没有及时沟通,形成后期维护成本大大提升,若是发现的早还好,在面临上线出现这样的问题,这必定是晴天大霹雳。swift
正确理解、肯定需求,对开发中选取第三方开源或者原生都是有很大帮助,能够大大下降后期维护成本。api
前段时间公司要接入摄像头来完成视频直播功能,采用m3u8格式实现,后期也不会有其它格式接入,从开发者文档中看到,Android原生控件仅支持MP4格式,对于其它格式的兼容,还存在很大问题,也就是说无法完美兼容m3u8。此时,咱们仅须要找到m3u8格式支持的方案就好,在搜索的征途中,咱们大大地缩小的范围。安全
作客户端开发,对于兼容性的话题,老是有千言万语,从最初写布局到后来的集成,再到后来系统的升级,无时无刻不在与兼容性打交道,尤为是在swift刚诞生的那一两年,每一个大版本都会大改api,这就有点扯淡了,搞的开发者心力交瘁,企业也不敢轻易尝试使用。bash
对于布局的适配的兼容性,今天不作讨论,接着上面视频对接的话题继续撸下去,通过一番对比,我把目标锁定在了Google的ExoPlayer和bilibili的ijkplayer,这两个都是开源项目,均可以在github找到源码,地址以下,点击可跳转:
ijkplayer的github地址:https://github.com/Bilibili/ijkplayer
ExoPlayer的github地址:https://github.com/google/ExoPlayer
我最初的选择方案更是倾向于ijkplayer,对国内开源项目原本就有一种特别的情感,国货当自强,和朋友讨论的时候,几个朋友也是推荐我ijkplayer,这其中也有B站的哥们,但他没参与到这个开源项目中,在最初跑demo的时候,确实能够完美播放m3u8,当我把他放到咱们项目中去的时候,发现报错了,再次检查下导入的包,以下:
dependencies {
# required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.3'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.3'
# Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.3'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.3'
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.3'
compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.3'
# ExoPlayer as IMediaPlayer: optional, experimental
compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.3'
}复制代码
发现导入的包没问题,打开源码看了下,是包的内部有冲突了,以下:
defaultConfig {
minSdkVersion 21
targetSdkVersion rootProject.ext.targetSdkVersion
}复制代码
最低支持21的版本,和项目有冲突,解决方案有三种,不导入64位的包,或者本身修改源码后从新编译,最后一种不现实,就是改公司项目的最低版本,咱们目前仍是有一部分Android 4.3的用户。
必定会有更好的方案,嗯,必定会有的,抱着试试看的态度,无心间发现了ExoPlayer。
经过一番查阅资料,在ExoPlayer的开发者文档中可看到
ExoPlayer’s standard audio and video components rely on Android’s MediaCodec API, which was released in Android 4.1 (API level 16). Hence they do not work on earlier versions of Android. Widevine common encryption is available on Android 4.4 (API level 19) and higher.
最低支持的版本是Android 4.1,公司目前项目,最低支持是Android 4.2,挺符合咱们的口味。
总结:兼容性一直是一个很繁琐的问题,版本更新太快,技术不断更新换代,一些不安全或者不必的方法,不断的从API中删去,接着迎来了一些新加入的API,合理的考察和调研,能够省去不少弯路。
对于健全性,主要体如今文档的健全性和资料的健全性,若是是一个全新的技术,官方没有提供健全的API,市面上尚未一些集成文档,这类的开源项目,最好别介入到项目中,做为第一个尝试吃蜘蛛的人,能够吃到的是一嘴的苦水。
最初我在测试ijkplayer的时候,首先,简单浏览了下内容,知道了个大概采用什么技术,接着就去找文档,天哪,我只看到了集成时候须要导入的包和编译采用的环境、工具,还有,就是我只找到了sample。这就尴尬了,这么大而优秀的项目,竟然没有官方文档,瞬间好感降低到了负一层,去网上搜了下资料,资料仍是很健全的,有不少优秀的开发者在集成后,把一些必要的注释就加上去了,看起来一目了然。
后来在调研Google的ExoPlayer的时候,发现有了质的差距,以下:
ExoPlayer 源码地址:
ExoPlayer api地址:
ExoPlayer 开发者指南:
这真的太棒了,集成的时候,能够解决少走不少弯路,遇到问题,也有了一些解决方案,扩展的时候,也为本身增长了几分信心。
想起了中学时候学校的一句标语:“细节决定成败,态度决定高度”。在平时使用或者学习第三方开源项目的时候,实现功能并非第一要素,更应该关注API和资料的健全性,这点,我一直很欣赏Google和square,Google先不提,在学习square的retrofit的时候,API仍是给了我很大的帮助,里面写的确实挺详细,一目了然,每一个注解都有详细的说明,让学习者感到更加亲切。
对于实现原理,一些初、中级开发者并不关注这个话题,总以为本身看不懂源码,看不懂那些所谓的高深技术,这个就是一个错误的态度,源码看不懂也很正常,诸如ijkplayer经过封装、修改和扩展FFmpeg去实现,FFmpeg,这个确实比较高深,虽然学过一段时间C语言,搞过一段时间FFmpeg,但对于内部一些代码,看的一样很吃力,但文档总能够看得懂的,再或者网上那么多资料,总能够了解个大概,至少能够知道ijkplayer支持的格式、采用的技术、解码的方式、须要的包...
以前一个前辈给个人忠告,若是一项技术,一个团队没人很熟悉,没人阅读和了解过源码,最好不要使用,一旦使用了,之后极可能会带来一大堆繁琐的问题。
确实是这样子的,就像三年多前在一家外包公司的时候,那时候市面上尚未太多关于即时聊天的文档,当时的第三方也没那么多选择,公司决定使用xmpp + openfire去实现,而那时候咱们团队没人接触过这一块内容,项目在爬行中推进,一个加好友的功能,把一个同事搞了好几天(这不否定那位同事的能力和粗心,由于英语的问题,没去看官方文档,同时也没过多的作调研)。
我很欣赏曹操,很欣赏他的疑人不用,用人不疑。若是曹操是一个程序员,必定是一位很优秀的代码家,以曹操的性格,必定会把一门技术吃透,而后再学以至用,触类旁通,尽量把一门技术发挥到极致。
无论采用什么样的开源项目,性能绝对是一个很重要的参考,就算这个项目写得再好,功能齐全,一旦性能有问题,这将是致命一击,就像一个失去双手的运动员,长、短跑都是第一,此时让他去参加乒乓球比赛,再牛逼的教练也是一脸懵逼。
回到刚才的话题,再ExoPlayer和ijkplayer中的选择,一大部分缘由是由于性能方面的问题,性能问题,直接把矛头指向了硬解码和软解码的区别。
硬解码:就是调用GPU的专门模块进行解码,由显卡核心GPU来对视频进行解码工做。
软解码:经过软件让CPU来对视频进行解码处理。
相信对于软解码和硬解码,大部分人都不陌生,这里不作多与赘述。
一图胜千言,作了一下对比:
上面对比中一个是功耗一个是总功耗,这个也很容易理解,GPU的电路更复杂,并行运算能力要远远高于CPU,因而耗电量就更高,GPU功耗大,但运行速度提高更多,功耗 = 功率 * 时间,因此就算功率乘个4,可是时间除以个10,总耗能仍是下降。
对于硬解码和软解码的选择,这个真心说不上哪一个更好,根据项目的须要,如今几乎全部的设备都支持硬解码和软解码,仅支持一种的Android移动设备已经属于古董级的,我是没见到过,以前更多的人愿意选择软解码,更大的缘由是由于硬件解码支持的格式较少,而软解码对于格式是不受限制的。
如今随着硬件的不断提升,解码技术的不断成熟和完善,我是更倾向硬解码,但硬件提高的同时,CPU也在不断的优化和提升,如今也不须要像以前那样尽量节省CPU,如今处于性能过剩的时代,CPU已经很难处于负荷状态,选择软解码或者硬解码都是没有谁对谁错,刚刚图上已经贴出和标记二者的优势,根据项目须要选择。
当时选择硬解码的ExoPlayer,是由于只须要播放m3u8格式的视频,画面上没有那么高的追求,对于这样的需求,硬解码更符合公司的口味和用户的体验,至少能够节省更多的电量。
对于产品常常改需求,这是常有的事,咱们更多的时间不该该是放在和产品经理撕逼,而是如何更好的应对这个问题。
刚学软件开发的时候,书上就提到,好的程序员,会更好的考虑代码的可维护性、可重用性、可扩展性和灵活性。
再接入一个第三方以前,熟悉它的功能是在所不免的事,就是由于某个和某几个功能吸引才致使咱们采用这个第三方,为了方便之后扩展,仍是应该多读几遍开发者文档,尽量多的了解和熟悉内部结构,在开发者文档,通常都会有详细的说明。
对于扩展性,这个就离不开文档和源码了,总不能本身莫名其妙的写代码,这不现实,我以为每一个合格的程序员都应该养成阅读源码的好习惯,这对自身的提升和功能的扩展都有很大的帮助。
对于集成性,我第一反应就是想到了微信和支付宝支付,这简直就是天壤之别,两年前的时候,我和一个同事分别接入支付宝和微信支付,我接入支付宝,加上阅读文档和跑demo,不到一个小时就跑通了,而他接入微信支付的时候,接了一天还没搞定,而后和我说微信支付的各类坑,当时也是半信半疑,就算坑了点,也不至于须要一天多吧,就这么点内容。后来有一次接了个私活,也是须要接入支付宝和微信支付,支付宝的文档很全很详细,微信的文档乱七八糟,更恶心的是回调的类还必须是一个固定包下面的固定类名,严重破坏了项目的包结构,深深的鄙视。
对于开放的SDK,我以为应该给接入者提供更加全面的文档,站在别的位置考虑下问题。
如何更加安全、高效地利用第三方开源项目,为了提升之后代码的可维护性和可扩展性,咱们应该更多的去调研和阅读开发者文档,磨刀不误砍柴工,一个好的开发者,应该把更多的时间放在思考和调研,而不是速度完成需求,而后把更多的时间放在改bug。