There are two kinds of people?:
?those who learn the hard way and those who learn by taking someone’s advice.
本文主要用來(lái)收集Android開(kāi)發(fā)中積累的一些寶貴經(jīng)驗(yàn),這些經(jīng)驗(yàn)中有一些約定熟成且經(jīng)過(guò)檢驗(yàn)的建議,有一些結(jié)合最新技術(shù)的實(shí)踐。無(wú)論是菜鳥(niǎo)還是大神,都應(yīng)該學(xué)會(huì)閱讀別人的經(jīng)驗(yàn),并結(jié)合自己的思考轉(zhuǎn)化成對(duì)自己有用的知識(shí),這才是最快的成長(zhǎng)之路。另外,對(duì)于這些建議,我會(huì)盡量翔實(shí)的進(jìn)行說(shuō)明以確保能夠順利快速應(yīng)用到實(shí)際開(kāi)發(fā)中。
下面以這篇文章:Building Android Apps?—?30 things that experience made me learn the hard way為核心,對(duì)其中提出的每一點(diǎn)建議進(jìn)行較為深入的分析探究,最終整理成一篇完整的文章。當(dāng)然,本文還在不斷更新中。
在你添加每一個(gè)third party library之前,請(qǐng)認(rèn)真考慮是否真的需要這個(gè)library。
如果用戶看不到,那就不要進(jìn)行繪制(draw),或者說(shuō),不要過(guò)度繪制 OverDraw
OverDraw
會(huì)導(dǎo)致GPU浪費(fèi),也會(huì)導(dǎo)致app的速度變慢。為了減少這種危害,我們可以利用Debug GPU Overdraw Tool來(lái)觀察app里的繪制情況,然后可以使用Hierarchy Viewer來(lái)進(jìn)行優(yōu)化。
除非不得不,否則不要使用database
Dalvik 65K methods limit
你很快就會(huì)遇到的,不過(guò)放心,multidexing會(huì)幫助你。
什么是Dalvik 65K methods limit
?我們知道,我們寫(xiě)完java code之后,dx tool會(huì)把java編譯成Dalivik虛擬機(jī)能識(shí)別的DEX
文件,這個(gè)文件里最多能夠索引65536個(gè)method
。關(guān)于這個(gè)有兩點(diǎn)要注意:
索引(reference)
到的,而不是定義(define)
的。或者說(shuō),如果你定義了一個(gè)方法,但這個(gè)方法并沒(méi)有被調(diào)用,那么就不算在內(nèi)。所以,我們總共可以索引65536
個(gè)方法,包括自己寫(xiě)的和引入第三方庫(kù)里的。
那么,我們?nèi)绾文芸焖僦牢覀兊腶pp里已經(jīng)有多少個(gè)method了呢?
現(xiàn)在,既然我們已經(jīng)知道了自家app里的method數(shù)了,那么如何來(lái)處理這種情況呢?
ProGuard
可以把code里unnecessary的method移除,壓縮apk,當(dāng)然還有代碼混淆
的奇效。DEX File
。把a(bǔ)pp里可以獨(dú)立的模塊或code提取出來(lái),放到一個(gè)獨(dú)立的dex文件里,你可以使用Custom ClassLoader來(lái)加載這些類,然后使用接口
或反射
來(lái)調(diào)用這些方法。不過(guò),這個(gè)過(guò)程還是比較麻煩的。RxJava, RxAndroid & Retrolambda
使用前可以通過(guò)這篇gist來(lái)了解RxJava+RxAndroid+Retrolambda的結(jié)合用法。這個(gè)組合可以優(yōu)雅的在不同線程中處理事務(wù),同時(shí)能夠方便的實(shí)現(xiàn)數(shù)據(jù)流動(dòng)和及時(shí)響應(yīng),而且Retrolambda能夠精簡(jiǎn)你的code。其中,核心的兩個(gè)概念是Observables
和Subscribers
,前者對(duì)外提供數(shù)據(jù),后者監(jiān)聽(tīng)并消費(fèi)這些數(shù)據(jù)。
另外,這里有一個(gè)看起來(lái)不錯(cuò)的項(xiàng)目Learning RxJava for Android by example,等空閑時(shí)再去閱讀下code。
Retrofit
+ RxJava利用Retrofit與RxJava結(jié)合,為你的app提供網(wǎng)絡(luò)請(qǐng)求服務(wù)。
你可以參考這個(gè)超贊的例子,讓你快速感受二者結(jié)合使用方法。
feature
來(lái)分package,而不是按layer
這是這篇文章提出的一個(gè)點(diǎn),文中認(rèn)為分package就像公司安排座位,要按照team
來(lái)分而不是按照每個(gè)人的職位來(lái)分,即按照負(fù)責(zé)一個(gè)app的developer、designer、pm
坐在一起,而不是把所有developer
坐在一起,所有designer
坐在一起。所以,原文作者認(rèn)為把一個(gè)feature相關(guān)的如Activity
adapter
等都放在一起。
不過(guò),我認(rèn)為按feature也有壞處,那就是復(fù)用
,拿adapter來(lái)講,一個(gè)app里很多adapter是類似且可以復(fù)用的,如果我們把各個(gè)adapter拆倒各個(gè)角落里,就很難提取其中的關(guān)聯(lián)來(lái)創(chuàng)建一個(gè)BaseAdapter
了。而且,不同feature之間也有很多公用的東西
,比如一個(gè)自定義view,那就很難界定應(yīng)該放在哪個(gè)feature包里了。相反,我們把所有自定義view放在一起,這樣也有助于我們發(fā)現(xiàn)某些自定義view的區(qū)別,然后在refactor時(shí)可以提取公用的東西來(lái)復(fù)用
。
關(guān)于這點(diǎn),歡迎讀者給出自己意見(jiàn)。
參考這篇文章來(lái)加速你的Gradle
這里有兩篇優(yōu)質(zhì)文章:Architecting Android…The clean way?和Architecting Android…The evolution 分別介紹并用code實(shí)現(xiàn)了一個(gè)Clean架構(gòu)。后面我也會(huì)專門(mén)分析下這種架構(gòu),因?yàn)閷?duì)于任何一個(gè)project而言,最初的好的架構(gòu)是非常重要的!所以,如果你想提高自己,那么架構(gòu)
這一關(guān)是必經(jīng)之路。
雖然做測(cè)試需要花費(fèi)你不少時(shí)間,但一旦你完成了這一步,以后的開(kāi)發(fā)會(huì)更加快速,app也會(huì)更加穩(wěn)定。
這里有個(gè)哥們,對(duì)unit test進(jìn)行了細(xì)致的點(diǎn)評(píng)。
依賴注入
神器Dagger
如果你不知道什么是依賴注入
,你可以先讀一下這篇文章Dependency injection on Android: Dagger (Part 1),或者這篇依賴注入。簡(jiǎn)單來(lái)說(shuō),依賴注入替代了傳統(tǒng)創(chuàng)建對(duì)象的new
操作,當(dāng)需要?jiǎng)?chuàng)建一個(gè)class的實(shí)例時(shí),使用依賴注入從外部直接獲取一個(gè)實(shí)例,具體這個(gè)實(shí)例是如何創(chuàng)建的不需要關(guān)心,由一個(gè)對(duì)象庫(kù)統(tǒng)一管理每個(gè)對(duì)象的創(chuàng)建過(guò)程,并直接對(duì)外提供對(duì)象。這樣做的好處是我們不用管實(shí)例是怎么創(chuàng)建的,這種抽象可以使得每個(gè)對(duì)象的創(chuàng)建過(guò)程變得可擴(kuò)展性,只要在對(duì)象庫(kù)里修改一次,那么所有用到這個(gè)實(shí)例的地方都隨之變更。例如在測(cè)試時(shí),我們希望某個(gè)mock某個(gè)對(duì)象的數(shù)據(jù),就可以修改注入的對(duì)象。
依賴注入有不少工具,不過(guò)Dagger2使用的是編譯時(shí)代碼生成(code generation)
方式而不是反射(reflection)
,所以它的性能比較出眾。這篇文章有對(duì)Dagger2的實(shí)踐和分析。
你可以通過(guò)Android Arsenal來(lái)保持對(duì)開(kāi)源項(xiàng)目的關(guān)注,同時(shí)利用這個(gè)工具dryrun來(lái)快速將開(kāi)源項(xiàng)目跑在genymotion以看到實(shí)際效果。
如果你創(chuàng)建了Service,那么一旦這個(gè)Service完成了自己的使命,就應(yīng)該立即清理掉它
使用AccountManager來(lái)統(tǒng)一管理用戶的賬號(hào)密碼。
持續(xù)集成CI(Continuous Integration)
來(lái)編譯并發(fā)布你的beta和release build持續(xù)集成可以幫助你方便的編譯并發(fā)布項(xiàng)目,不過(guò),不要去搭建你們自己的CI服務(wù)器,因?yàn)槟阈枰ㄙM(fèi)太多的時(shí)間來(lái)處理硬盤(pán)空間、安全問(wèn)題和預(yù)防SSL攻擊等問(wèn)題。你可以嘗試Jenkins、circleci、 travis 或者 shippable,這些價(jià)格并不貴,而且能幫你省很多事情。
你可以使用這個(gè)工具gradle-play-publisher來(lái)幫助你自動(dòng)上傳apk到Play Store上
理由很簡(jiǎn)單,android developer應(yīng)該很熟悉每次導(dǎo)入一張圖片時(shí)都需要生成四五種不同大小的png圖片并放入到對(duì)應(yīng)文件夾。與其維護(hù)這么多圖片,顯然使用一張svg圖片更加方便。而且,google也在不斷提供相關(guān)的支持,除了基本的Vector Drawable,從最新的Support Library我們也能看到google也在鼓勵(lì)developer們使用svg。
不過(guò),svg也有自己的限制,比如它比較適合小icon,因?yàn)樗罱K會(huì)生成bitmap加載以供顯示,所以這需要一定的cpu支持。當(dāng)然總體來(lái)講svg還是更優(yōu)的,至少大家可以不用再維護(hù)四五張不同尺寸的圖片了。
例如,一旦我們打log會(huì)使用Log.i()
,但是,如果后面我們突然想換成Timber.i()
就會(huì)很麻煩,需要一個(gè)個(gè)log找到來(lái)替換。但是,如果我們抽象出一個(gè)AppLogger
來(lái),全部調(diào)用AppLogger.i()
來(lái)記log,那么我們只要簡(jiǎn)單的在AppLogger
內(nèi)部替換掉具體實(shí)現(xiàn)就可以了。
移動(dòng)數(shù)據(jù)流量
和Wi-Fi
;同樣,可以監(jiān)控電量
和充電狀態(tài)
對(duì)于不同網(wǎng)絡(luò)類型,我們可以動(dòng)態(tài)改變我們的UI,比如大圖可以選擇在Wi-Fi
下才加載,而在移動(dòng)數(shù)據(jù)流量
則不加載。對(duì)于電量
也是類似的邏輯。用戶一定會(huì)很感謝app做的這種自適應(yīng)的。
本文長(zhǎng)期更新,會(huì)保持跟蹤最新的技術(shù)和研究實(shí)踐經(jīng)驗(yàn),為大家提供有效有用的經(jīng)驗(yàn),少走坑。
歡迎各位關(guān)注
我的Github: https://github.com/wingjay
和
我的個(gè)人博客: http://wingjay.com
和
我的簡(jiǎn)書(shū): http://www.jianshu.com/users/da333fd63fe5/latest_articles
和
微博 iam_wingjay: http://weibo.com/u/1625892654
如果有問(wèn)題,可以給我留言或發(fā)郵件yinjiesh@126.com
聯(lián)系客服