Android studio Instant run與multidex的奮鬥記
話說,我android的開發機器是一部雙核心的ibm r61筆電, 有4G的ram t8300 cpu, 跑eclipse是還算順暢, 本以為這樣子用, 可以撐上一段時日, 但好景不常, 隨著我的專案愈寫愈大,有一天可怕的事發生了, 那就是65536的惡夢, 原來android有限制不能寫超過65536個函數。
65536, 我又不是在開發windows 10或android 6。 怎麼可能會超過65536個函數. 原來不是這樣算的, 要把所有用到的jar都算進去。那些加入基本的 jar 動不動就七千八千。還有的1萬2萬的, 隨便一加總就超過65536了。
我開始想辦法解決,方法是把dex拆成多個,這樣就不會超過65536,所以稱為multi dex,但在eclipse上面真的解法都很麻煩,試了很多方法都不行,好不容易找到一個最簡單的方法,就是套用別人做好的方案,也成功了,但最後要做release版的時候,又出了問題,怎麼都無法克服。終於只好轉移到android studio。
本來真不太想用android studio 的。原因是電腦等級不夠,曾經安裝了一次,試了試,實在是跑不太動。後來又移除了,雖然比eclipse好用。但eclipse用熟了, 其實也還好. 但這一次實在是被multidex的問題給搞慘了。本來用eclipse處理multidex已經成功了99%了, 但最後用proguard產生apk時, 遇到問題居然一直無法解決。只好又重新安裝了android studio , 但沒想後來的專案, 又加入了一個相當大40mb的 jar 包,一放上去用 android studio 編譯執行的速度,真的是慢到無法忍受, 每次改個程式碼, 關掉所有的程序, 只留android studio都要跑個十幾分鐘,如果再開個瀏覽器,跑半個小時,都出不來。本來想放棄, 再重回eclipse的懷抱,再與muti-dex奮鬥一次。
就在此時救星出現了,Android Studio 1.5 提示我有新版的2.0可更新,我查看有何新功能,救星就是新版的Android Studio 2.0 內的Instant Run。Instant Run 顧名思義,就是快速run,所謂快速,就是每次更改程式碼,Instant Run 只針對修改的部分編譯,然後就可以執行了,不必每次都重來。每次從編譯到執行時間,都是用秒計算的,當然可以省很多時間,這真是老電腦的福音。
我又找了許多資料,大概明白Instant Run的作法,你如果不會使用,建議參考這一篇,算是蠻詳細的。開發速度快 50 倍:詳解 Android Studio 2.0 的殺手功能 Instant Run
當我一步一步照著做的時候,出現一個錯誤訊息如下:
Instant Run is disabled: Instant Run does not support deploying build variants with multidex enabled, to a target with API level 20 or below. To use Instant Run with a multidex enabled build variant, deploy to a target with API level 21 or higher.
又扯到multi-dex,我就是因為這個multi-dex的問題才投到Android Studio的陣營來,現在又看到這個,看來好像很嚇人的樣子, 不會是因為我用到multi-dex 不能用instant run吧. 趕快google一下這個訊息。
在這一篇提到:
http://stackoverflow.com/questions/35405040/cannot-instant-run-legacy-multi-dex-on-dalvik-runtimehttp://stackoverflow.com/questions/35405040/cannot-instant-run-legacy-multi-dex-on-dalvik-runtime
In order to activate multiDex at old android versions you have to set multiDexEnabled to true, add dependency and extend your application class from MultiDexApplication or launchMultiDex.install(this) in your application class, which will cause legacy multiDex installation.
However since Intant Run can't work with legacy multiDex you have to use normal one. All you need is removing all that code above except of multiDexEnabled flag set to true. This method is only supported by devices with API 21 and above.
依他的說法, 要把之前改成可以用multi-dex的部分還原, 只留multiDexEnabled 設成true這一部分, 那這樣子, 還能保有multi-dex的功能嗎? 那我還不如回eclipse好了。
不死心, 再找看有沒有別的解法:
開發速度快 50 倍:詳解 Android Studio 2.0 的殺手功能 Instant Run
提到:
1.將 minSdkVersion 改成 21
2.或是將專案根目錄下 build.gradle 的 gradle dependency 改回
classpath 『com.android.tools.build:gradle:1.3.0』 ,當然,這樣就沒有 Instant Run 的能力了
3.等官方釋出新的版本
很顯然的, 這些都不是答案, 因為將 minSdkVersion 改成 21, 那android 4.X不就全放棄了嗎
再找, 又找到這一篇:
instant run can't support multidex
提到InstantRun does support multidex out of the box when targeting Emulator or Devices that are are least API 21 (Lollipop or Marshmallow). Are you trying to target a device with 19 during development ?
沒錯,我用target device並非api 21 以上的機器,我是用android 4.2的手機, 當測試機。於是我改用genymotion,並找一個api 21, android 5.0的模擬器版本來用。 測試一下, 果然一切都正常,而且什麼minSdkVersion,什麼MultiDexApplication,我都沒更動,就可以直接用instant run了,原來只要測試用的手機不使用android 5.0以前的版本,就可以在multidex下,使用instant run。不瞭解為什麼前面幾文章,寫得如此複雜。測試結果,雖然不像別人說的,每次使用instant run 只花二秒三秒。但從來也沒超過一分鐘,大部分的時間都在20秒以內。這對我那台先前動不動就要跑個十幾二十分鐘的機器,我已經很滿意了。
我到目前為止會造成全部重新編譯的情況有:
1.更換測試的手機 (因為很多dex檔案是放在手機根目錄內相關app的資料夾內)
2.解除已安裝的app
3.大幅度修改程式碼
4.adb device offline或unconected的時候
而修改res資料夾內xml的內容,我遇到的情況,還是會使用instant run,不會全部重來。
最後又看到這一篇,
Android 在 Multidex 下使用 Instant Run
有提到用gradle
使用gradle中的Build Variant可以做到不用每次都更改minSdkVersion還能使用Instant Run。
雖然不知為何要改minSdkVersion, 不過記下來當備忘, 以後也許會用到
不過雖然使用instant run沒什麼大問題,但也出現一些小問題:
1.曾出現原始碼, 除錯時,有對不起來的情況, 這時, 我在原始碼不符合的部分, 按enter加了一空白行, 再重debug, 就正常了。
2.也出現過新寫了個class, 編譯時都沒錯, 但執行時, 卻當在別的地方參考到此一class時, 出現找不到的情況, 同樣在那個class的程式碼, 加了個空白行, 再重run 也正常了
3.本來好像可以用instant run 但半途卻出現什麼apk找不到之類的, 也不知問題在那裡, 只好rebuild project, 但這一來就不是用 instant run , 而是全部重來了,但之後再使用時就正常了。