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。