版權信息
原文鏈接:[編譯提速最佳實踐](https://juejin.im/post/5831301a0ce463006c044c77)
---
本文會不定期更新,推薦watch下項目。如果喜歡請star,如果覺得有紕漏請提交issue,如果你有更好的點子可以提交pull request。本文意在分享作者在實踐中對于打包和build的提速方案,如果你有更好的點子可以在下方進行評論補充。
本文固定連接:[github.com/tianzhijiex…](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Ftianzhijiexian%2FAndroid-Best-Practices)
# 需求
讓打包變得更快一點,再快一點!
這個需求簡單明了,就是要更快的打包,減少時間上的浪費。
# 實現
## 分析目前現狀
### build-time-tracke
[build-time-tracke](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fpassy%2Fbuild-time-tracker-plugin)是可以檢測出build耗時的gradle插件,會形成十分美觀的圖表,可以方便的確定當前的編譯時間和主要耗時的task。

### gradlew build -profile
`gradlew build -profile`命令會生成報表,`gradlew build assembleDebug -profile`會產生debug模式下的報表,報表位置在工程的根目錄下的build目錄中。


### dexcount
[dexcount](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2FKeepSafe%2Fdexcount-gradle-plugin)也是一個相當不錯的統計工具,也是一個gradle插件。
配置后執行build會產生目前的方法數的輸出,也會輸出一個圖表。
~~~
> ./gradlew assembleDebug
...buildspam...
:app:compileDebugSources
:app:preDexDebug UP-TO-DATE
:app:dexDebug
:app:packageDebug
:app:zipalignDebug
:app:assembleDebug
Total methods in MyApp-debug-5.3.14.apk: 56538
BUILD SUCCESSFUL
Total time: 33.017 secs
~~~

利用這個圖表我們可以方便的分析出不同庫的不同方法,對于查看復雜庫和精簡方法有著相當重要的幫助。
## 精簡工程
### 刪除不必要的module
AS的代碼結構和eclipse完全不同,它為開發者提供了單工程多module的形式。但多建立一個module就需要多維護一個module,而且依賴的module越多,編輯時間越久,甚至有人說是依賴aar或jar的四倍時間。
如果僅僅是為了方便寫代碼而建立一個module是不可取的,我強烈建議先做好項目結構的梳理再考慮是否需要建立module。
下面是一個多module的app結構圖:

framework
在as中通過自帶的預覽工具,也可以幫助我們進行modules的梳理:

module
這個項目中的module有很多,所以gradle在編譯的時候會去檢測module的依賴鏈,gradle會幫助我們層層梳理module之間的關系,避免因為module之間相互引用而來帶的問題。這些梳理工作和module的合并工作都會增加build的時間。
如果你的項目build十分緩慢,我強烈建議你去梳理下module的關系,合并部分module,將穩定的底層module打包為aar,上傳到公司的maven倉庫,借此來加快build速度。
### 刪除module中的無用文件
as默認在建立module的同時會建立test目錄:

test
如果你根本沒有編寫過測試用例,你完全可以刪除test目錄,到要寫的時候再加上就好。
當然,如果你的module就是純代碼,根本沒用到資源文件,也請一并把res目錄刪除掉。

res
### 刪除主項目中無用的資源文件
項目開發中多少都會存留一些無用的代碼和資源,資源越多打包合并資源的時間就越長。對于資源文件,as提供了自動檢測失效文件和刪除的功能,絕對值得一試。

remove res
在彈出的對話框中,我強烈建議不要勾選刪除無用的id,因為databinding會用到一些id,但這在代碼中是沒有直接依賴的,因此as會認為這些是無用id,會直接刪除。如果你刪除了這些id,那么就等著編譯失敗吧。(別問我是怎么知道的T_T)。順便說一下,每次做這種操作前記得commit一下,方便做diff。

dialog
## 優化依賴庫
### 利用no-op加快debug的速度
如果項目中有很多公司自己的module依賴,那么你完全可以采用類似于[這篇文章](https://link.juejin.im/?target=http%3A%2F%2Fwww.liaohuqiu.net%2Fposts%2Fspeed-up-your-build%2F)提到的技巧,給私有的module做no-op(什么是no-op可以看[這篇](https://link.juejin.im/?target=http%3A%2F%2Fwww.liaohuqiu.net%2Fposts%2Fspeed-up-your-build%2F)的例子)。
一般私有的module會比較穩定,并且對外暴露的方法不多,甚至會是別的項目組開發的。在不影響功能的前提下,建議和開發團隊商量提供no-op版本。
~~~
debugCompile(project(':share-lib-no-op')) {}
releaseCompile(project(':share-lib')) {}
debugCompile(project(':zxing-no-op')) {}
releaseCompile(project(':zxing')) {}
~~~
用no-op版本的好處就是只使用接口而不使用實現,將實現的代碼全部剔除,如果做的好的話甚至可以在debug時不用multidex,但壞處就是需要進行協作交流。如果module對外的接口變動了,還應該考慮到對no-op版本的影響。
### 減少方法數,不使用multidex
關于什么是multidex,和怎么使用它,請參考[《使用android-support-multidex解決Dex超出方法數的限制問題》](https://link.juejin.im/?target=http%3A%2F%2Fblog.csdn.net%2Ft12x3456%2Farticle%2Fdetails%2F40837287)
它是一種不得已而為之的舉措,使用它后我經常會發現在一些特殊的機型上會出現一些奇奇怪怪的錯誤,總之就是有很多坑。
在build時間這一塊,multidex因為有分包和壓縮的過程,所以它對于編譯速度方面有有嚴重的影響。我通過dexcount這個插件分析了我的項目后,發現項目中有一些庫已經不再用或者有更好的替代品,于是我精簡和替換了第三方庫,并且開啟了support包的混淆,最終讓我們的項目的release包的方法數達到了一個合理的水平。

優化前

精簡庫,開啟support包的混淆后
為了控制變量,我專門用一個空項目進行support包混淆前后的對比。數據如下:

混淆前

混淆后
當一個第三方sdk說不要混淆support包,不要混淆我sdk的代碼的時候,我強烈建議你考慮下方法數的問題。混淆的作用之一是將代碼進行優化和縮短方法名、字段名;作用之二就是刪除沒有被用到的變量和方法。第三方sdk的方法數眾多,如果沒辦法混淆,那么會帶來大量的方法數,這點需要十分的小心。混淆雖然是一個十分有用的工具,但也是很多錯誤的來源,所以我建議你小心謹慎的多多使用它!
### 根據使用場景依賴不同庫
上面講到了優化第三方庫會減少方法數,這里簡單講一下一般的優化策略:
1. 利用`debugCompile`來依賴debug時才用到的庫
`debugCompile`我在[第三方庫開發實踐](https://link.juejin.im/?target=http%3A%2F%2Fwww.jianshu.com%2Fp%2F0aacd419cb7e)中已經講到多次了,這里就不再贅述。
2. 利用更小的庫替代現有的庫
這個就要看開發人員的經驗和知識面和判斷能力了。雖然是廢話,如果能真正做到,成果是極其明顯的。
3. 利用exclude來排出某些不需要的依賴
react native是一個龐大的庫,引入rn后會依賴很多別的庫:

rn
在我們的項目中,我利用了自己編寫的網絡請求模塊進行網絡請求,所以我就想要剔除掉rn引入的okhttp。我還發現它引入了support包,而我項目中也有support包,所以我也想要排出掉它(不排除support包也沒事,gradle會僅包含最新的庫版本,我這里僅僅是舉個例子)。
~~~
compile ('com.facebook.react:react-native:+'){
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'support-v7'
}
~~~
重新build一次后,你會發現okhttp已經被剔除掉了:

exclude okhttp
對于本地的module也是可以這樣處理的:
~~~
compile(project(':react-native-custom-module')) {
exclude group: 'com.facebook.react', module: 'react-native'
}
~~~
## 利用緩存
### 開啟offline
這個是最簡單直接的加速方案了,效果極其明顯,誰用誰知道!

offline

### 用公司的倉庫做緩存
我推薦的做法是項目中所有的依賴(私有或第三方)都通過公司的倉庫進行獲取。公司的倉庫應該能自己查找jcenter等倉庫,下載好需要的依賴,并進行緩存。這樣的好處是:當一個同事引入了新庫或者更新庫版本后,別的同事在build時可以直接拿緩存好的庫,大大減少了下載依賴的時間。這點雖然是小優化,但是對于新人和團隊協作來說是相當重要的。
## 跳過無用的耗時操作
### debug時跳過某些task
我們的項目中用到了很多gradle插件,有些插件會在build時運行自己的task:

gradle plugin
* [tiny](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fmogujie%2FTinyPIC_Gradle_Plugin)是用來壓縮圖片的
* [buildtime](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fpassy%2Fbuild-time-tracker-plugin)是用來檢測build時間的
* [dexcount](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2FKeepSafe%2Fdexcount-gradle-plugin)是用來分析方法數的
這些插件對于我們的開發工作帶來了巨大的幫助,但也增加了build時間。
我分享下我的做法:
1. 在每次發版本前開啟tiny,直接build一次,壓縮完圖片后將其關閉。
2. 在需要檢測和診斷build時間的時候啟用buildtime,一般的debug時不開啟它。
3. 在release包中開啟[dexcount](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2FKeepSafe%2Fdexcount-gradle-plugin),并且讓其于Jenkins進行結合。這樣既不會影響debug包,又可以進行方法數的持續監控。
關于dexcount是如何和Jenkins結合的,并且是如何產生下面的圖表的,請參考:
[www.th7.cn/Program/And…](https://link.juejin.im/?target=http%3A%2F%2Fwww.th7.cn%2FProgram%2FAndroid%2F201606%2F870070.shtml)

dexcount
關于如何在不同的情況下跳過或啟用task的知識,可以參考[Gradle配置實踐](https://link.juejin.im/?target=http%3A%2F%2Fgold.xitu.io%2Fpost%2F582d606767f3560063320b21)中的內容。
### 跳過lint
通過`gradlew build -profile`我們可以得到build的詳細報告,最終報告會生成在根目錄的`build/reports/profile`中:


我們可以看到lint的時間占到了build時間的80%之多,所以如果你不在意lint的結果的話,你可以在build時跳過lint檢測,比如:
> gradle build -x lint -x lintVitalRelease
因為我用命令行build的次數較少,所以我直接在gradle中加了一個跳過lint的task:
~~~
tasks.whenTaskAdded { task ->
if (task.name.equals("lint") || task.name.equals("lintVitalRelease")) {
task.enabled = false
}
}
~~~
### 放棄retrolambda,謹慎使用AspectJ
目前android不支持lambda,所以很多人都引入了[retrolambda](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Forfjackal%2Fretrolambda)。一旦你引入了這個庫,你就必須面臨著字節碼轉換而帶來的build慢的問題。它需要在build時執行一個插入代碼的task,這個task的執行時間隨著你用的越多而會越來越長。所以,我不推薦在目前的階段使用它,還是等等看看谷歌jack的表現吧(jack目前還是太初級,對庫和增量編譯的支持很差)。
AspectJ是aop的工具,但因為需要在build時進行代碼的插入,所以使用AspectJ后build時間會明顯的增加,具體看使用量而定。
AspectJ的優缺點十分明顯,我這里只是提出來,具體如何權衡,就看大家自己了。我因為用了[UiBlock](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Ftianzhijiexian%2FUiBlock%2F)所以引入了AspectJ,它讓我debug是build的速度慢了三秒鐘,但UiBlock的好處也十分明顯,所以我還是用了這個庫。
## 優化配置方案
### 在dev環境中設置minSdkVersion為21
因為在debug時,我們不會去開啟混淆,所以debug包常常是需要用mulitdex的。

debugApplication
android5.0對于mulitdex做了優化,具體可以參考官方的文章,我就直接說怎么做就好。先在gradle的配置中添加一個flavors,比如叫做dev,在dev中配置最低支持的android版本為21.

gradle
然后在build時選中`devDebug`,這樣你debug的時候就是走最低支持21的編譯方式了。

build
特別注意:
現在我們為了提速將最低版本寫為21,假設你最終可能支持的是16,這就有個風險點了。因為as會在你寫代碼的時候認為你的應用就是支持21的,所以對于一些16~21的api不會有版本風險提示的。因此使用16~21之間的api時需要人為的注意,這是最大的風險!!!
### 升級jdk和gradle
最新的Gradle要比老版本要快,jdk1.8比jdk1.6要快,所以可以跟著官方升級新版本就好。
> The same argument goes for Java versions as well. If you haven’t upgraded yet to Java 8, do it now! Well finish reading this blog post, but do it straight afterwards! You don’t even have to move your project to use Java 8, lambdas and so on. Just make sure your build tool executes with the latest and the most performant Java version out there.
### 調整gradle的編譯參數
gradle.properties中允許我們進行各種配置:
配置大內存:
~~~
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
~~~
守護進程
~~~
org.gradle.daemon=true
~~~
并行編譯
~~~
org.gradle.parallel=true
~~~
開啟緩存:
~~~
android.enableBuildCache=true
~~~
開啟孵化模式:
~~~
org.gradle.configureondemand=true
~~~
以上的配置需要針對自身進行選擇,隨意配置大內存可能會出現oom。如果想了解這樣配置的原理,請移步[官方文檔](https://link.juejin.im/?target=https%3A%2F%2Fdocs.gradle.org%2Fcurrent%2Fuserguide%2Fbuild_environment.html)。
我自己的配置如下:
~~~
org.gradle.daemon=true
org.gradle.parallel=true
android.enableBuildCache=true
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
~~~
總的來說,除了增加內存這一項感覺還有點用處外,其余配置都不痛不癢。我最后直接加了16g內存,解決了大多數的問題。
### 配置大內存
~~~
android {
dexOptions {
// 使用增量模式構建
incremental true
// 最大堆內存
javaMaxHeapSize "4g"
// 是否支持大工程模式
jumboMode = true
// 預編譯
preDexLibraries = true
// 線程數
threadCount = 8
// 進程數
maxProcessCount 4
}
}
~~~
在app的build.gradle中配置大內存也可以有效的提升build速度。
> 上面有些配置方案在最新的gradle中已經標記為無效了,可以適當的刪除掉。
### 優化crashlytics的upload
上面講到的都是build過程中的提速,但打包過程不僅僅包含了build,還包含了混淆,簽名等流程。如果你的項目用了[crashlytics](https://link.juejin.im/?target=https%3A%2F%2Ffabric.io%2Fkits%2Fandroid%2Fcrashlytics),crashlytics會在混淆時自動上傳map文件到服務器,這樣可以幫助你在分析崩潰的時候看到的是混淆前的代碼和行數,十分方便。
萬事有利有弊,我們項目的map文件為6m左右,crashlytics的服務器又是在國外,所以每次都會需要很長的一段時間。
優化點主要是提升上行帶寬和網絡速度,前者需要硬件的支持,后者可以通過vpn進行優化。在配置release包打包命令的時候,可以不用每次都把build目錄刪除,這在一定程度上也可規避此問題。
### 利用MultiChannelPackageTool進行多渠道打包
我們的應用可能會被分發到多個渠道,而我們又想進行多個渠道的數據分析,這就產生了目前android要打多個渠道包的現狀。[這篇文章](https://link.juejin.im/?target=http%3A%2F%2Fgeek.csdn.net%2Fnews%2Fdetail%2F76488)詳細的分析了國內最高效的打包方案,文章短小精干,值得一讀。
我選擇的是[MultiChannelPackageTool](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fseven456%2FMultiChannelPackageTool)來進行打包,它的速度是最快的,而且使用方式十分的簡單。他的原理是在zip文件的comment中加入渠道號,這樣既可以寫入渠道號又不會破壞zip的簽名,因為apk本身就是一個zip文件,所以這個規則是可靠并完全通用的。

comment
具體的原理和實現方案也不難,這里可以參考趙林寫的[《一種動態為apk寫入信息的方案》](https://link.juejin.im/?target=http%3A%2F%2Fpingguohe.net%2F2016%2F03%2F21%2FDynimac-write-infomation-into-apk.html%3Fcomefrom%3Dhttp%3A%2F%2Fblogread.cn%2Fnews%2F)進行深入了解。
下面我給大家演示下實際的情況:

package
現在我們可以通過
~~~
MCPTool.getChannelId(context, "password", "")
~~~
得到渠道名稱。如果你用的是友盟來做監控和統計,那么你肯定需要在代碼中設置友盟的key和channel名。通過友盟的文檔和論壇我發現友盟最新的sdk提供了這樣的配置機制,于是就有了如下代碼:
~~~
// 設置key和渠道號,在application中就需要進行設置
UMAnalyticsConfig config = new UMAnalyticsConfig(context, appKey, channelId);
MobclickAgent.startWithConfigure(config);
// 得到key和渠道號
String appKey = AnalyticsConfig.getAppkey(activity);
String channel = AnalyticsConfig.getChannel(activity);
~~~
## 采用增量編譯
### instant Run

Instant Run是谷歌的一套解決方案,兼容性肯定是一流的,但是對于奔潰和調試來說經常不盡人意,只能靜待其發展了。
### jirebel

jirebel
as目前已經支持了增量編譯,但是效果真的很差,甚至經常會增加build時間,所以這里我還是推薦一直在更新的[Jrebel](https://link.juejin.im/?target=http%3A%2F%2Fzeroturnaround.com%2Fsoftware%2Fjrebel-for-android%2F)做增量編譯的工具。
我之前寫[《Android中UI實時預覽實踐》](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Ftianzhijiexian%2FAndroid-Best-Practices%2Fblob%2Fmaster%2F2015.9%2Fui%2Fui.md)的時候就有推薦過它,只不過那時候真的太貴了。現在as出了增量編譯,它也坐不住了,立刻降價,價錢還算是可以接受。它的優點是成熟穩定,各種配套服務支持的十分完善,但crash 后仍舊需要重新全量編譯,單次全量編譯、安裝的速度非常慢。一個更大的風險點在于每次gradle更新它都是必須要更新的,使用的時候經常要調試這方面的問題。
如果你寫的是小型應用的話,效果會更好。現在它已經不用我們單獨配置maven倉庫了,完全和項目解耦,而且它竟然支持注解和aop,堪稱黑科技!所以,如果你有心想要加快打包的速度,我強烈推薦你去試用上21天,看看它是否值得你為之付費。
### freeline

如果你想試試免費的工具,那么[freeline](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Falibaba%2Ffreeline)絕對是你的首選。
幾個月來,它發展迅速,也配備了as插件gradle插件,支持各種平臺。關于它的原理,可以參考[《Freeline - Android平臺上的秒級編譯方案》](https://link.juejin.im/?target=https%3A%2F%2Fyq.aliyun.com%2Farticles%2F59122)進行了解。
freeline只支持python2.7版本,對于重命名等操作支持力度不足,不支持 databinding,不支持刪除帶id 的資源。實際使用中還是會發現要經常clean后build,對于不同的`flavor`也是沒辦法動態切換,只能寫死:
~~~
freeline {
hack true
productFlavor 'dev'
}
~~~
總體來說freeline算是目前免費的增量編譯中的最優秀的作品了,值得一試。
關于各種增量工具的對比可以參考:[Android 加速構建方案對比 - DiyCode](https://link.juejin.im/?target=https%3A%2F%2Fwww.diycode.cc%2Ftopics%2F369)
# 尾聲
本文的需求相當簡單明了,但實現起來卻都是八仙過海各顯神通,并沒有所謂的一站式解決方案。其實技術的走向也是如此,各個技術的涌現都是為了解決實際需求中的問題,脫離業務而出現的技術方案是走不遠的。早期android中app偏向簡單,對于打包時間并沒有過于在意。隨著移動化進程的發展,app過于復雜和龐大,打包提速變得十分重要,這也是纂寫本文的初衷。
提速的涉及面很廣,涉及到庫開發、方法數、電腦平臺、app瘦身等多個領域,也希望大家在閱讀完畢后能夠有所收獲,在以后遇到提速需求的時候可以有一些解決思路。
- 0-發現
- AndroidInterview-Q-A
- Android能讓你少走彎路的干貨整理
- LearningNotes
- temp
- temp11
- 部分地址
- 0-待辦任務
- 待補充列表
- 0-未分類
- AndroidView事件分發與滑動沖突處理
- Spannable
- 事件分發機制詳解
- 1-Java
- 1-Java-01基礎
- 未歸檔
- 你應該知道的JDK知識
- 集合框架
- 1-Java-04合集
- Java之旅0
- Java之旅
- JAVA之旅01
- JAVA之旅02
- JAVA之旅03
- JAVA之旅04
- JAVA之旅05
- JAVA之旅06
- JAVA之旅07
- JAVA之旅08
- JAVA之旅09
- java之旅1
- JAVA之旅10
- JAVA之旅11
- JAVA之旅12
- JAVA之旅13
- JAVA之旅14
- JAVA之旅15
- JAVA之旅16
- JAVA之旅17
- JAVA之旅18
- JAVA之旅19
- java之旅2
- JAVA之旅20
- JAVA之旅21
- JAVA之旅22
- JAVA之旅23
- JAVA之旅24
- JAVA之旅25
- JAVA之旅26
- JAVA之旅27
- JAVA之旅28
- JAVA之旅29
- java之旅3
- JAVA之旅30
- JAVA之旅31
- JAVA之旅32
- JAVA之旅33
- JAVA之旅34
- JAVA之旅35
- 1-Java-05辨析
- HashMapArrayMap
- Java8新特性
- Java8接口默認方法
- 圖解HashMap(1)
- 圖解HashMap(2)
- 2-Android
- 2-Android-1-基礎
- View繪制流程
- 事件分發
- AndroidView的事件分發機制和滑動沖突解決
- 自定義View基礎
- 1-安卓自定義View基礎-坐標系
- 2-安卓自定義View基礎-角度弧度
- 3-安卓自定義View基礎-顏色
- 自定義View進階
- 1-安卓自定義View進階-分類和流程
- 10-安卓自定義View進階-Matrix詳解
- 11-安卓自定義View進階-MatrixCamera
- 12-安卓自定義View進階-事件分發機制原理
- 13-安卓自定義View進階-事件分發機制詳解
- 14-安卓自定義View進階-MotionEvent詳解
- 15-安卓自定義View進階-特殊形狀控件事件處理方案
- 16-安卓自定義View進階-多點觸控詳解
- 17-安卓自定義View進階-手勢檢測GestureDetector
- 2-安卓自定義View進階-繪制基本圖形
- 3-安卓自定義View進階-畫布操作
- 4-安卓自定義View進階-圖片文字
- 5-安卓自定義View進階-Path基本操作
- 6-安卓自定義View進階-貝塞爾曲線
- 7-安卓自定義View進階-Path完結篇偽
- 8-安卓自定義View進階-Path玩出花樣PathMeasure
- 9-安卓自定義View進階-Matrix原理
- 通用類介紹
- Application
- 2-Android-2-使用
- 2-Android-02控件
- ViewGroup
- ConstraintLayout
- CoordinatorLayout
- 2-Android-03三方使用
- Dagger2
- Dagger2圖文完全教程
- Dagger2最清晰的使用教程
- Dagger2讓你愛不釋手-終結篇
- Dagger2讓你愛不釋手-重點概念講解、融合篇
- dagger2讓你愛不釋手:基礎依賴注入框架篇
- 閱讀筆記
- Glide
- Google推薦的圖片加載庫Glide:最新版使用指南(含新特性)
- rxjava
- 這可能是最好的RxJava2.x入門教程完結版
- 這可能是最好的RxJava2.x入門教程(一)
- 這可能是最好的RxJava2.x入門教程(三)
- 這可能是最好的RxJava2.x入門教程(二)
- 這可能是最好的RxJava2.x入門教程(五)
- 這可能是最好的RxJava2.x入門教程(四)
- 2-Android-3-優化
- 優化概況
- 各種優化
- Android端秒開優化
- apk大小優化
- 內存分析
- 混淆
- 2-Android-4-工具
- adb命令
- 一鍵分析Android的BugReport
- 版本控制
- git
- git章節簡述
- 2-Android-5-源碼
- HandlerThread 源碼分析
- IntentService的使用和源碼分析
- 2-Android-9-辨析
- LRU算法
- 什么是Bitmap
- 常見圖片壓縮方式
- 3-Kotlin
- Kotlin使用筆記1-草稿
- Kotlin使用筆記2
- kotlin特性草稿
- Kotlin草稿-Delegation
- Kotlin草稿-Field
- Kotlin草稿-object
- 4-JavaScript
- 5-Python
- 6-Other
- Git
- Gradle
- Android中ProGuard配置和總結
- gradle使用筆記
- Nexus私服搭建
- 編譯提速最佳實踐
- 7-設計模式與架構
- 組件化
- 組件化探索(OKR)
- 1-參考列表
- 2-1-組件化概述
- 2-2-gradle配置
- 2-3-代碼編寫
- 2-4-常見問題
- 2-9-值得一讀
- 8-數據結構與算法
- 0臨時文件
- 漢諾塔
- 8-數據-1數據結構
- HashMap
- HashMap、Hashtable、HashSet 和 ConcurrentHashMap 的比較
- 遲到一年HashMap解讀
- 8-數據-2算法
- 1個就夠了
- Java常用排序算法(必須掌握的8大排序算法)
- 常用排序算法總結(性能+代碼)
- 必須知道的八大種排序算法(java實現)
- 9-職業
- 閱讀
- 書單
- 面試
- 面試-01-java
- Java面試題全集駱昊(上)
- Java面試題全集駱昊(下)
- Java面試題全集駱昊(中)
- 面試-02-android
- 40道Android面試題
- 面試-03-開源源碼
- Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執行流程
- 面試-07-設計模式
- 面試-08-算法
- 面試-09-其他
- SUMMARY
- 版權說明
- temp111