已收藏,可在 我的資料庫 中查看
您可能還需要
獨(dú)立站
國潮領(lǐng)航?破浪出海
立即報(bào)名
加入社群
獨(dú)立站近期活動(dòng)

小紅書Android客戶端演進(jìn)之路

小紅書Android客戶端第一個(gè)版本于2014年8月8日發(fā)布,轉(zhuǎn)眼到了2016年8月8日,小紅書Android版本發(fā)版兩周年。趁機(jī)回顧一下小紅書的Android版本,兩年中我們踩過很多坑,收獲很多經(jīng)驗(yàn),分享出來與大家共勉。

小紅書Android客戶端演進(jìn)之路

小紅書Android客戶端第一個(gè)版本于2014年8月8日發(fā)布,轉(zhuǎn)眼到了2016年8月8日,小紅書Android版本發(fā)版兩周年。趁機(jī)回顧一下小紅書的Android版本,兩年中我們踩過很多坑,收獲很多經(jīng)驗(yàn),分享出來與大家共勉。

小紅書從最初1.0到現(xiàn)在目前4.7版本,歷經(jīng)兩年,安裝包從原先的5M發(fā)展到現(xiàn)在的17M,產(chǎn)品模塊也從原先的只有社區(qū)模塊發(fā)展到了具有社區(qū)和電商兩個(gè)大模塊。App包含社區(qū)、電商、支付、推送、直播、統(tǒng)計(jì)等各種功能和模塊,那么開始吧。

功能演進(jìn)

兩年的時(shí)間,30多個(gè)版本的迭代,許多功能都有了翻天覆地的變化。我們的新人歡迎頁也是從最初的比較炫的效果發(fā)展到目前比較穩(wěn)定的簡(jiǎn)潔版本。當(dāng)初鐘大俠花了無數(shù)個(gè)日日夜夜,苦心做出來了多個(gè)歡迎頁動(dòng)畫,雖然現(xiàn)在已經(jīng)不再使用,但是我們也學(xué)習(xí)到了一些新技術(shù)。后來,鐘大俠還是將其貢獻(xiàn)到了github開源社區(qū)中。

小紅書Android客戶端演進(jìn)之路

小紅書Android客戶端演進(jìn)之路

社區(qū)是小紅書的核心價(jià)值之一,筆記是小紅書社區(qū)的核心體現(xiàn),毋庸置疑,筆記發(fā)布是小紅書App的核心功能之一,我們一直在產(chǎn)品和技術(shù)上,優(yōu)化我們的筆記發(fā)布流程和功能,包括我們將只支持分享單張圖片,擴(kuò)展到現(xiàn)在支持多張圖片同時(shí)發(fā)布。同時(shí)支持更豐富的圖片編輯效果,更加便捷的發(fā)布筆記。

小紅書的筆記展現(xiàn)形式和大多數(shù)其他的圖片社交App類似,我們也支持圖上標(biāo)簽功能。最初小紅書圖上標(biāo)簽是同其他App類似的黑色的標(biāo)簽。不過在3.0之后,小紅書創(chuàng)造了獨(dú)特的樹狀標(biāo)簽,給用戶帶來煥然一新的體驗(yàn),同時(shí)也被其他App競(jìng)相模仿。新的標(biāo)簽給技術(shù)也帶了很多的挑戰(zhàn),我們重新定義了標(biāo)簽的結(jié)構(gòu),以及標(biāo)簽的生成和展示。

UI的改版,功能上的改動(dòng)還有很多,這里不再一一提起。小紅書Android整體上的風(fēng)格和iOS保持一致,不過我們?cè)?5年初開始,對(duì)于App內(nèi)的細(xì)節(jié)進(jìn)行Material Design 適配,包括一些按鈕風(fēng)格、點(diǎn)擊效果、字體規(guī)范、對(duì)話框等等,希望為Android用戶帶來更好的使用體驗(yàn)。

技術(shù)選型進(jìn)化

在技術(shù)選型上,這里主要講一下網(wǎng)絡(luò)層的框架選型升級(jí)和圖片加載庫的升級(jí)。

網(wǎng)絡(luò)框架的演進(jìn)

App的最初框架是由鐘大俠一人花了10來天完成,包括基本的網(wǎng)絡(luò)請(qǐng)求框架、App大體的架構(gòu)以及一些主要的功能。最初時(shí)候選擇框架的原則就是選擇自己最熟悉的,因此我們采用了async-http這套框架作為我們底層的網(wǎng)絡(luò)請(qǐng)求框架,框架完成了網(wǎng)絡(luò)的異步請(qǐng)求與回調(diào),能夠滿足當(dāng)時(shí)的需求。

然而僅僅不到半年之后,我們就決定了使用Volley來替換。替換以后,底層的網(wǎng)絡(luò)請(qǐng)求代碼更加清晰,在Volley返回的結(jié)果即直接返回了我們需要的Object,同時(shí)將統(tǒng)一的錯(cuò)誤處理、公共的參數(shù)處理和一些公共的返回使用的參數(shù),全部放在我們自定義的Request當(dāng)中,這樣外部請(qǐng)求所需要傳入的參數(shù)更少,對(duì)于錯(cuò)誤的處理更加簡(jiǎn)單,只需要考慮業(yè)務(wù)需要的Response,其他全局的返回內(nèi)容則無需進(jìn)行干擾。通過Volley的引入,幫助我們?cè)跇I(yè)務(wù)的開發(fā)上變得更加便捷。引入Volley之初,Volley的底層使用的是HttpClient+HttpURLConnection,后期通過網(wǎng)上的資料發(fā)現(xiàn)OkHttp使用NIO更加高效,并且被Android 引入作為系統(tǒng)底層的網(wǎng)絡(luò)請(qǐng)求,我們也將Volley的底層也替換為OkHttp。

與此同時(shí),小紅書的api請(qǐng)求也在不斷進(jìn)行RESTful,我們遇到一個(gè)問題就是經(jīng)常找一個(gè)api的定義比較麻煩。大約在15年11月份,我們引入了Retrofit,通過二次改造,使其支持了公共參數(shù)的構(gòu)建,以及對(duì)于GsonConvert的改進(jìn)支持直接返回我們需要的Object,而且對(duì)于RESTful風(fēng)格的良好支持給我們提供了極大的便利。配合RxJava,我們可以方便的進(jìn)行多個(gè)api的同時(shí)請(qǐng)求、api返回的多個(gè)線程的切換。

圖片加載框架的演進(jìn)

小紅書的筆記是以圖片加文字為主體的內(nèi)容,因此會(huì)有大量的圖片顯示需求。和網(wǎng)絡(luò)框架選型類似,早期選擇了比較熟悉的UIL來做圖片加載,可以同時(shí)支持本地圖片和網(wǎng)絡(luò)圖片的加載,在當(dāng)時(shí)可以滿足我們的基本需求。

15年初,我們開始使用更加高清的圖片,隨之加載速度變慢,占用更多的內(nèi)存,而且這個(gè)時(shí)候UIL的作者基本很少維護(hù)。我們開始調(diào)研使用新的圖片加載框架。此時(shí)Fresco剛剛出來,還不太穩(wěn)定,當(dāng)時(shí)沒敢用。給我們的可選項(xiàng)有Picasso和Glide兩個(gè)可選項(xiàng),Picasso比較輕量,但是相比于UIL在性能上沒有太好的提高。Glide代碼量較大,不過它會(huì)在本地保存多份緩存(原始圖片和實(shí)際顯示尺寸的圖片),這樣加載本地緩存的時(shí)候,可以直接顯示大小剛好的尺寸,減少解碼的時(shí)間,因此會(huì)比UIL要快很多。

15年下半年,我們需要支持gif的動(dòng)畫顯示,而Glide對(duì)動(dòng)畫的兼容性又不是特別好,這個(gè)時(shí)候我們直接切到了Fresco。同時(shí)Fresco對(duì)webp的良好支持,使得我們?cè)诤笃谇袚Q到webp格式的時(shí)候,減少了很多工作量。Fresco在4.4及以下版本使用匿名內(nèi)存來作為內(nèi)存緩存,為我們減少OOM做了巨大的貢獻(xiàn)。

我們使用的這幾個(gè)圖片加載框架,每個(gè)框架的使用都有非常大的區(qū)別,這就導(dǎo)致遷移的時(shí)候工作量巨大。為了降低遷移成本,我們封裝了自己的ImageLoader,在ImageLoader中來實(shí)現(xiàn)具體的圖片加載,這樣保證在遷移的時(shí)候,最大程度的降低代碼的改動(dòng)(不過在遷移到Fresco的時(shí)候還是改動(dòng)巨大,因?yàn)槲覀儾荒苤苯邮褂肐mageView了。

推送的升級(jí)

推送,我覺得也有必要說一說。最初我們快速選用了百度云推送,在當(dāng)時(shí)看來百度的推送比較穩(wěn)定,同時(shí)接入比較簡(jiǎn)單。實(shí)際使用了一年之后,發(fā)現(xiàn)送達(dá)率不是特別高,并且數(shù)據(jù)統(tǒng)計(jì)做的不太好,無法比較好的統(tǒng)計(jì)推送效果。在調(diào)研之后,我們決定遷移到小米推送+友盟推送的模式,針對(duì)小米用戶開啟小米推送,其他用戶采用友盟推送,為了平滑過渡,在切換期間同時(shí)向未升級(jí)的老用戶繼續(xù)使用百度云推送進(jìn)行推送。

架構(gòu)升級(jí)

由于一直以來在業(yè)務(wù)開發(fā)占用的時(shí)間比較多,目前App的整體架構(gòu)沒有做過太大的改變。

在Adapter的使用方面,我們將ListView或RecyclerView的Item放到單獨(dú)的ItemHander,這樣可以在不同的頁面可以通過將不同的Item組裝到一起,從而滿足不同地方的需求。這樣可以在ListView或RecyclerView來復(fù)用相同的代碼,提高代碼的可維護(hù)性。

前面網(wǎng)絡(luò)層說到我們的錯(cuò)誤處理,這個(gè)也是做過比較大的升級(jí)。最初時(shí)候,網(wǎng)絡(luò)錯(cuò)誤、http請(qǐng)求錯(cuò)誤、后臺(tái)和客戶端的錯(cuò)誤,都分別在不同的層級(jí)進(jìn)行處理。目前我們?cè)诎l(fā)生錯(cuò)誤的時(shí)候?qū)㈠e(cuò)誤全部以Exception的方式拋出,最后在上層進(jìn)行錯(cuò)誤的處理。

App中的狀態(tài)同步,早期使用使用數(shù)據(jù)庫緩存部分?jǐn)?shù)據(jù),或者使用LocalBroadcast進(jìn)行廣播通訊,前者有很多的限制,后者使用起來較為復(fù)雜。近期我們改用EventBus進(jìn)行狀態(tài)同步,同時(shí)這樣也使得各個(gè)頁面之間的耦合也低。

App中占比很大的部分是從網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),獲得數(shù)據(jù)后進(jìn)行展示,還是以MVC為主。在一些模塊的部分地方,做一些databinding,MVP等的測(cè)試。后面有機(jī)會(huì)會(huì)更多大范圍的重構(gòu)。

其他周邊進(jìn)化

我們的開發(fā)最初是使用Eclipse進(jìn)行開發(fā)的,但是Eclipse僅僅存在了不到一個(gè)月。在我苦口婆心的勸說下,鐘大俠和我一起切換到了Android Studio。而這導(dǎo)致我們的項(xiàng)目目錄一直都是使用Eclipse時(shí)代的目錄格式,直到今年年初才切換到Android Studio推薦的目錄格式,切換完目錄為我們做debug和release差異化提供了極大的便利。

APK最初大約只有5M,歷史最高峰達(dá)到了23M,在App減肥上我們也做了一些努力,主要是使用tinypng壓縮圖片,so只保留arm的支持。項(xiàng)目的復(fù)雜也使得每次編譯都變得很慢,關(guān)于這個(gè)可以看下我以前的gradle加速

現(xiàn)在持續(xù)集成還是蠻火的,自然我們也在用。最初的時(shí)候,我們每天需要手動(dòng)打包,打完包之后打開fir的網(wǎng)站,將apk傳上去,然后在公司的微信群吼一聲,告訴大家我們發(fā)包了。經(jīng)歷一段時(shí)間后,我們編寫了一個(gè)Gradle插件幫助我們自動(dòng)上傳到fir,在之后我們搭建了Jenkins自動(dòng)完成這一系列步驟,并通過郵件告知大家,然后就可以愉快的玩耍了。

小紅書Android客戶端演進(jìn)之路

未完待續(xù)

本文介紹了我們兩年來的一些大的變化,通過一篇文章可能很多東西還是說不清楚,暫時(shí)就寫這么多。目前項(xiàng)目的組織架構(gòu)還沒有特別大的變化,我們目前已經(jīng)在做一些小范圍的測(cè)試,后面將對(duì)繼續(xù)不斷的進(jìn)化和演進(jìn)。

以上內(nèi)容屬作者個(gè)人觀點(diǎn),不代表雨果網(wǎng)立場(chǎng)!

相關(guān)標(biāo)簽:

分享到:

--
評(píng)論
最新 熱門 資訊 資料

收藏

--

--

分享