Android開發(fā)中的那些坑

這些坑主要分為幾個(gè)類:分為系統(tǒng)API的坑、使用不當(dāng)導(dǎo)致的坑、開源項(xiàng)目中的坑等幾個(gè)方面

1.系統(tǒng)API的坑##

(1) Android library中的資源ID在R.java中不是final類型:
??問(wèn)題現(xiàn)象:在library中使用switch語(yǔ)句區(qū)分不同的資源ID時(shí),IDE會(huì)報(bào)錯(cuò);
??原因分析:這個(gè)問(wèn)題在Android Studio Project Site (http://tools.android.com/tips/non-constant-fields)有提及,在ADT14及以上的版本中,library所對(duì)應(yīng)的R.java中所有ID不再是final類型,所以不能將ID作為switch語(yǔ)句中的case分支屬性值。這個(gè)問(wèn)題和IDE無(wú)關(guān),在Eclipse和AS中都存在。
??解決方案:如果涉及到區(qū)分多個(gè)ID的情況(比如監(jiān)聽回調(diào)事件、初始化通過(guò)xml給自定義View設(shè)置的屬性值等)應(yīng)該使用if...else if...else代替switch語(yǔ)句;

(2) 同一個(gè)程序內(nèi)的多個(gè)進(jìn)程之間使用SharedPreferences不安全:
??問(wèn)題現(xiàn)象:在同一個(gè)程序內(nèi)使用多進(jìn)程時(shí),在不同進(jìn)程間使用SharedPreferences操作數(shù)據(jù)會(huì)導(dǎo)致SF中的數(shù)據(jù)隨機(jī)丟失的情況(獲取到的值為空);
??原因分析:雖然API中提供了Context.MODEMULTIPROCESS模式打開SF文件,但在官方文檔(https://developer.android.com/reference/android/content/SharedPreferences.html)中已有說(shuō)明:“currently this class does not support use across multiple processes”,因?yàn)镾F在多進(jìn)程間操作是不安全的,并行操作時(shí)會(huì)導(dǎo)致寫沖突。
??解決方案:Github上有個(gè)開源項(xiàng)目Tray(https://github.com/grandcentrix/tray),專門針對(duì)在多進(jìn)程中使用SF不安全的問(wèn)題提供的解決方案。

(3) Typeface初始化自定義字體慢:
??問(wèn)題現(xiàn)象:在使用自定義字體的頁(yè)面,進(jìn)入慢;
??原因分析:使用Typeface初始化字體很耗時(shí),至少需要100ms(不同文件耗時(shí)不一樣)以上的時(shí)間。
??解決方案:如果在Activity的onCreate方法中初始化Typeface,會(huì)導(dǎo)致進(jìn)入Activity慢,出現(xiàn)黑屏/白屏現(xiàn)象,所以應(yīng)該盡量在非UI線程中做自定義字體的初始化操作。

(4) Activity在沒(méi)有完全顯示/已退出的情況下顯示PopupWindow異常:
??問(wèn)題現(xiàn)象:進(jìn)入Activity界面直接報(bào)錯(cuò),log異常顯示為:"Unable to add window -- token null is not valid";
??原因分析:原因是在Activity的onCreate方法中直接顯示了PopupWindow導(dǎo)致,PopupWindow的顯示是依附在某一個(gè)View上面的(showAtLocation方法第一個(gè)參數(shù)為需要依附的view),在Activity沒(méi)有完全顯示時(shí),PopupWindow無(wú)法依附在該View上,如果在此時(shí)顯示PopupWindow會(huì)導(dǎo)致上面的異常,同樣在退出Activity后也不能正常顯示PopupWindow。
??解決方案:在開發(fā)過(guò)程中需要考慮通過(guò)異步顯示PopupWindow,避免PoupWindow顯示報(bào)異常的問(wèn)題。

(4) Activity的onDestory方法調(diào)用時(shí)機(jī)不確定:
??問(wèn)題現(xiàn)象:連續(xù)進(jìn)入、退出某一個(gè)Activity,會(huì)出現(xiàn)Activity Crash掉的現(xiàn)象;
??原因分析:在Activity的onCreate做的初始化操作(打開文件),在onDestory做的銷毀操作(關(guān)閉文件);退出Activity后onDestory并沒(méi)有立即調(diào)用,再次快速進(jìn)入該Activity時(shí),該Activity是另外一個(gè)實(shí)例,并且首先調(diào)用了新Activity的onCreate方法之后再才調(diào)用上個(gè)Activity實(shí)例的onDestory方法,導(dǎo)致文件剛被打開就關(guān)閉了,在程序使用數(shù)據(jù)時(shí)Crash掉;
??解決方案:準(zhǔn)確來(lái)講只要是系統(tǒng)方法,調(diào)用時(shí)機(jī)都不確定。對(duì)于這種問(wèn)題只能盡量不要在Activity的系統(tǒng)回調(diào)方法中做資源初始化和釋放的操作,比如涉及到IO操作的情況,在使用的時(shí)候才打開,使用完后立即關(guān)閉;

(5) 透明主題導(dǎo)致Activity生命周期回調(diào)的變化:
??問(wèn)題現(xiàn)象:從當(dāng)前Activity跳轉(zhuǎn)到其它Activity時(shí),當(dāng)前Activity的onStop方法并沒(méi)有調(diào)用;
??原因分析:給當(dāng)前Activity設(shè)置為透明主題導(dǎo)致,通過(guò)添加打印跟蹤發(fā)現(xiàn),從該Activity跳轉(zhuǎn)到其它Activity時(shí),該Activity的onStop方法不會(huì)執(zhí)行;
??解決方案:謹(jǐn)慎使用透明主題,如果必須要為Activity設(shè)置為透明主題,不要在onStop方法中做任何操作,因?yàn)樵摲椒ú⒉粫?huì)被調(diào)用。透明主題存在很多問(wèn)題,比如在設(shè)置為透明主題的界面按Home按鍵時(shí),會(huì)存在界面刷不干凈的情況。

(6) 不要通過(guò)Bundle傳遞很大塊的數(shù)據(jù):
??問(wèn)題現(xiàn)象:從目錄界面跳轉(zhuǎn)到內(nèi)容顯示界面,出現(xiàn)隨機(jī)崩潰的現(xiàn)象,報(bào)的異常是:TransactionTooLargeException;
??原因分析:跟蹤發(fā)現(xiàn)如果通過(guò)Bundle傳遞太大塊(>1M)的數(shù)據(jù)會(huì)在程序運(yùn)行時(shí)報(bào)TransactionTooLargeException異常,具體原因可以上官網(wǎng)查看,大致意思是傳遞的序列化數(shù)據(jù)不能超過(guò)1M,否則會(huì)報(bào)TransactionTooLargeException異常;之所以隨機(jī)是因?yàn)槊看蝹鬟f的數(shù)據(jù)大小不一樣。
??解決方案:如果你在不同組件之間傳遞的數(shù)據(jù)太大,甚至超過(guò)了1M,為了提高效率和程序的穩(wěn)定性,建議通過(guò)持久化的方式傳遞數(shù)據(jù),即在傳遞方寫文件,在接收方去讀取這個(gè)文件;

(6) 不要在Application類中緩存數(shù)據(jù):
??問(wèn)題現(xiàn)象:程序從后臺(tái)切換到前臺(tái),直接崩了;
??原因分析:程序在后臺(tái)時(shí),為了給正在運(yùn)行的程序提供更多可使用的內(nèi)存,Application中的數(shù)據(jù)可能會(huì)被清理掉,如果在Application中緩存了數(shù)據(jù),并且在程序重新回到前臺(tái)時(shí)沒(méi)有做好恢復(fù)工作,程序會(huì)出現(xiàn)不可預(yù)見的情況(比如數(shù)據(jù)錯(cuò)亂、崩潰等),具體可以參照這篇文章Don't Store Data in the Application Object;
??解決方案:不要在Application中緩存數(shù)據(jù)。

(7) 使用AsyncTask無(wú)法避開的坑:
??問(wèn)題現(xiàn)象:使用AsyncTask異步執(zhí)行的任務(wù)并沒(méi)有立即執(zhí)行;
??原因分析:AsyncTask這個(gè)類的實(shí)現(xiàn)可謂一波三折,方案修改了好幾個(gè)版本,初次引入這個(gè)類時(shí),所有的Task是放在一個(gè)獨(dú)立的后臺(tái)線程中執(zhí)行的,也就是如果有多個(gè)Task同時(shí)被調(diào)用也是順序執(zhí)行的;從1.6開始,改為通過(guò)線程池可以支持并行執(zhí)行多個(gè)Task;但從3.0開始,又改回只有一個(gè)獨(dú)立的后臺(tái)線程執(zhí)行所有Task,主要是為了避免多個(gè)Task并行執(zhí)行導(dǎo)致的程序錯(cuò)誤,但為了讓AsyncTask能夠支持多個(gè)Task并行執(zhí)行,從3.0起,增加了executeOnExecutor方法,調(diào)用者自行實(shí)現(xiàn)線程池可以達(dá)到并行多個(gè)Task的效果。
??解決方案:如果在某個(gè)地方需要同時(shí)執(zhí)行多個(gè)異步任務(wù),強(qiáng)烈建議使用線程池;

(8) 數(shù)據(jù)庫(kù)升級(jí)中的坑:
??問(wèn)題現(xiàn)象:在數(shù)據(jù)庫(kù)的某個(gè)表中增加/修改了某個(gè)字段后,程序在運(yùn)行時(shí)崩潰掉了;或者在增加字段時(shí)修改了數(shù)據(jù)庫(kù)的版本號(hào),但程序升級(jí)后,原來(lái)的數(shù)據(jù)丟失了;
??原因分析:SQlite數(shù)據(jù)庫(kù)升級(jí)時(shí)需要修改OpenHelper中的版本號(hào),并且數(shù)據(jù)庫(kù)升級(jí)會(huì)刪掉原來(lái)數(shù)據(jù)庫(kù)中的數(shù)據(jù),需要手動(dòng)將原數(shù)據(jù)庫(kù)中的數(shù)據(jù)拷貝到高版本的數(shù)據(jù)庫(kù)中;
??解決方案:做好數(shù)據(jù)庫(kù)升級(jí)的恢復(fù)工作,避免出現(xiàn)崩潰、數(shù)據(jù)丟失的情況。

(9) 程序在未啟動(dòng)的情況下,靜態(tài)注冊(cè)的廣播無(wú)法收到消息:
??問(wèn)題現(xiàn)象:程序添加了對(duì)開機(jī)廣播的監(jiān)聽,但無(wú)法接收到;
??原因分析:這個(gè)問(wèn)題只有在程序安裝但沒(méi)有啟動(dòng)時(shí)才會(huì)出現(xiàn),只要程序啟動(dòng)過(guò)一次后就不會(huì)有這個(gè)問(wèn)題。并且只有在Android 3.1及以上的版本才會(huì)出現(xiàn),具體原因是:從Android3.1開始,新安裝的程序會(huì)被置于"stopped"狀態(tài),并且只有在至少手動(dòng)啟動(dòng)這個(gè)程序一次后該程序才會(huì)改變狀態(tài),能夠正常接收到指定的廣播消息。Android這樣做的目的是防止廣播無(wú)意或者不必要地開啟未啟動(dòng)的APP后臺(tái)服務(wù)。也就是說(shuō)在Android3.1及以上的版本,程序在未啟動(dòng)的情況下通過(guò)應(yīng)用自身完成一些操作是不可能的,但Android提供了一種借助其它應(yīng)用發(fā)送指定Flag廣播的方式,達(dá)到應(yīng)用在未啟動(dòng)的情況下仍然能夠收到消息的效果。從Android 3.1開始,系統(tǒng)給Intent定義了兩個(gè)新的Flag,分別為FLAGINCLUDESTOPPEDPACKAGES(表示包含未啟動(dòng)的App)和FLAGEXCLUDESTOPPEDPACKAGES(表示不包含未啟動(dòng)的App),用來(lái)控制Intent是否要對(duì)處于停止?fàn)顟B(tài)的App起作用。
??解決方案:只能借助其它應(yīng)用給自己發(fā)送帶FLAG_INCLUDESTOPPEDPACKAGES標(biāo)志的廣播才能實(shí)現(xiàn)在程序未啟動(dòng)的情況下接收到廣播;

(10) android:windowBackground導(dǎo)致的過(guò)渡繪制問(wèn)題:
??問(wèn)題現(xiàn)象:界面的布局已無(wú)法進(jìn)一步優(yōu)化,但仍然存在過(guò)渡繪制的問(wèn)題;
??原因分析:window存在默認(rèn)的背景,會(huì)增加過(guò)渡繪制的可能。Activity是依附在Window上的,如果給Activity設(shè)置了背景,并且沒(méi)有去掉window的背景,很容易導(dǎo)致過(guò)渡繪制;這里還有一個(gè)坑,有的應(yīng)用為了避免程序冷啟動(dòng)時(shí)出現(xiàn)黑屏/白屏的問(wèn)題,在主題中給window設(shè)置了背景,并且在Activity的布局中給Activity也設(shè)置了背景,這會(huì)導(dǎo)致當(dāng)前界面存在兩個(gè)背景,占用了雙倍的內(nèi)存,并且還會(huì)有過(guò)渡繪制的問(wèn)題。程序啟動(dòng)黑屏應(yīng)該去優(yōu)化性能問(wèn)題,而不是采用給window設(shè)置背景的方式;
??解決方案:可以通過(guò)給Activity自定義主題,在主題中去掉window的默認(rèn)背景,即:@null;

(11) 類的finalize方法調(diào)用時(shí)機(jī)不確定:
??問(wèn)題現(xiàn)象:程序隨機(jī)崩潰;
??原因分析:多個(gè)地方用到了同一個(gè)類,該類用于對(duì)數(shù)據(jù)的IO操作,打開文件后并沒(méi)有立即關(guān)閉,也沒(méi)有釋放資源的public方法,主要通過(guò)類的finalize方法關(guān)閉文件,釋放資源;
??解決方案:finalize方法的調(diào)用時(shí)機(jī)是不確定的,不要指望通過(guò)該方法釋放與類相關(guān)的資源,避免出現(xiàn)隨機(jī)的bug;

(12) Fragment isAdded:
??問(wèn)題現(xiàn)象:程序隨機(jī)崩潰;
??原因分析:跟蹤異常log發(fā)現(xiàn),是因?yàn)镕ragment沒(méi)有完全顯示或者已經(jīng)離開Fragment的情況下,導(dǎo)致的異常,這類異常的主要原因是:使用Fragment時(shí),通過(guò)異步操作(比如回調(diào)、非UI線程等)更新Fragment的狀態(tài),但此時(shí)Fragment沒(méi)有完全顯示或者已經(jīng)離開Fragment;
??解決方案:在調(diào)用Fragment的方法之前,強(qiáng)烈建議調(diào)用isAdded方法判斷Fragment是否依附在Activity上,避免出現(xiàn)異常。

(13) Fragment hide、show被調(diào)用時(shí),生命周期不會(huì)回調(diào):
??問(wèn)題現(xiàn)象:同一界面不同F(xiàn)ragment之間切換時(shí),并沒(méi)有觸發(fā)一些動(dòng)態(tài)效果,比如播報(bào)音頻、顯示切換動(dòng)畫等;
??原因分析:Fragment hide、show被調(diào)用時(shí),系統(tǒng)并不會(huì)調(diào)用Fragment的生命周期回調(diào);
??解決方案:不同F(xiàn)ragment之間切換時(shí),主動(dòng)調(diào)用各個(gè)Fragment的生命周期回調(diào);

2.使用不當(dāng)造成的坑##

(1) 9圖不要用tinypng壓縮:
??問(wèn)題現(xiàn)象:使用壓縮工具壓縮9圖后,顯示變形;
??原因分析:9圖除了圖片信息外,還存儲(chǔ)一些Android在顯示9圖過(guò)程中需要用到的必要信息,通過(guò)壓縮工具壓縮圖片會(huì)改變文件的信息,9圖被壓縮后程序能顯示,但顯示的效果無(wú)法達(dá)到預(yù)期,因?yàn)槔煨畔G失了。
??解決方案:9圖文件本身就不大,沒(méi)必要壓縮;
(2) 同一設(shè)備上,相同程序的圖片放在不同drawable文件夾下,占用內(nèi)存不一樣:
??問(wèn)題現(xiàn)象:程序剛啟動(dòng)就占用了很高的內(nèi)存;
??原因分析:圖片放置位置不合理導(dǎo)致的,程序在不同的設(shè)備中運(yùn)行時(shí),會(huì)根據(jù)設(shè)備的分辨率和屏幕密度去從與之分辨率匹配的資源文件夾中取圖片,如果沒(méi)有對(duì)應(yīng)分辨率的文件夾,則從相近分辨率的文件夾中取,但圖片會(huì)被拉伸到當(dāng)前設(shè)備屏幕的寬高,所以會(huì)存在圖片被放大或者縮小的問(wèn)題,導(dǎo)致占用內(nèi)存會(huì)隨之變化,具體可以查看這篇博客關(guān)于Android中圖片大小、內(nèi)存占用與drawable文件夾關(guān)系的研究與分析(http://blog.csdn.net/zhaokaiqiang1992/article/details/49787117);
??解決方案:為了減少UI的工作量,并且減少APK的內(nèi)存占用的方法是讓UI出一套高分辨率版本的圖片,放在hdpi文件夾下。

(3) Adapter ViewHolder緩存導(dǎo)致顯示錯(cuò)亂的坑:
??問(wèn)題現(xiàn)象:ListView每一項(xiàng)在滑動(dòng)的過(guò)程中內(nèi)容顯示錯(cuò)亂;
??原因分析:在Adapter的getView方法中通過(guò)position更新每一項(xiàng)的內(nèi)容時(shí),對(duì)于根據(jù)判斷條件給每一項(xiàng)設(shè)置屬性的情況,每個(gè)判斷條件下都需要給每一項(xiàng)的每個(gè)屬性賦值,否則在滑動(dòng)ListView或GridView時(shí)會(huì)導(dǎo)致內(nèi)容錯(cuò)亂;
??解決方案:在getView方法里面,給每一項(xiàng)都要設(shè)置對(duì)應(yīng)的屬性,比如給每一項(xiàng)的頭像設(shè)置圖片,如果某一項(xiàng)沒(méi)有頭像,不能不設(shè)置,應(yīng)該設(shè)置為透明,否則會(huì)錯(cuò)亂。

(4) Toast連續(xù)顯示時(shí)長(zhǎng)時(shí)間不消失:
??問(wèn)題現(xiàn)象:多個(gè)Toast同時(shí)顯示時(shí),Toast一直顯示不消失,退出程序了仍然顯示;
??原因分析:看Toast的源碼可以發(fā)現(xiàn),同時(shí)顯示多個(gè)toast時(shí)是排隊(duì)顯示的,所以才會(huì)出現(xiàn)同時(shí)顯示多個(gè)Toast時(shí)很久都不消失的情況;
??解決方案:這屬于體驗(yàn)問(wèn)題,很多應(yīng)用都存在。建議定義一個(gè)全局的Toast對(duì)象,這樣可以避免連續(xù)顯示Toast時(shí)不能取消上一次Toast消息的情況(如果你有連續(xù)彈出Toast的情況,避免使用Toast.makeText);

(5) build.gradle中的versionName和versionCode:
??問(wèn)題現(xiàn)象:從Eclipse轉(zhuǎn)到AS的項(xiàng)目,在機(jī)器上運(yùn)行時(shí)報(bào)版本比之前APK版本低的錯(cuò)誤;
??原因分析:從Eclipse轉(zhuǎn)到AS的過(guò)程中,如果你是通過(guò)AS直接新創(chuàng)建的一個(gè)工程,注意模板會(huì)在build.gradle中給程序設(shè)置默認(rèn)versionName和versionCode為1,如果AndroidManifest.xml中的versionCode、versionName比build.gradle中的更高,會(huì)導(dǎo)致因?yàn)榘姹締?wèn)題安裝不上的情況(報(bào)INSTALL_FAILEDVERSIONDOWNGRADE錯(cuò)誤);
??解決方案:只在build.gradle中設(shè)置版本名和版本號(hào);

(6) AS中依賴包的動(dòng)態(tài)更新:
??問(wèn)題現(xiàn)象:依賴包頻繁更新,因?yàn)锳S編譯有緩存,每次更新都需要修改依賴包的版本號(hào),特別麻煩,特別是依賴關(guān)系比較復(fù)雜的情況下;
??解決方案:在AS中,如果你想動(dòng)態(tài)同步一個(gè)依賴包的更新,可以在依賴包的最后面寫上“+”,比如:compile 'com.android.support:appcompat-v7:23.0.+' ,但這種方法需要謹(jǐn)慎使用,否則會(huì)因?yàn)橐蕾嚢淖儎?dòng)導(dǎo)致你的項(xiàng)目不穩(wěn)定:Don't use dynamic versions for your dependencies
(https://link.zhihu.com/?target=http%3A//blog.danlew.net/2015/09/09/dont-use-dynamic-versions-for-your-dependencies/);

(7) AS中同一個(gè)工程module太多導(dǎo)致編譯慢:
??問(wèn)題現(xiàn)象:編譯一個(gè)工程要好幾分鐘,特別是clean的時(shí)候,經(jīng)常10分鐘以上;
??原因分析:其實(shí)這個(gè)很好理解,每個(gè)module中都有一個(gè)build.gradle,編譯的時(shí)候,每個(gè)module的build.gradle中的task都需要執(zhí)行,所以編譯時(shí)間會(huì)很長(zhǎng)。
??解決方案:要解決這個(gè)問(wèn)題很簡(jiǎn)單,將不經(jīng)常變動(dòng)的module打包成aar,主工程依賴aar而不是module,這樣避免了每次都需要重新編譯module的情況。

(8) 頻繁的GC操作導(dǎo)致程序卡頓:
??問(wèn)題現(xiàn)象:通過(guò)AS Monitor觀察應(yīng)用運(yùn)行過(guò)程中的內(nèi)存抖動(dòng)厲害,通過(guò)GPU呈現(xiàn)模式觀察每一幀的曲線差別很大,整體感受程序運(yùn)行時(shí)不流暢;
??原因分析:在2.3之前GC操作是不能并發(fā)進(jìn)行的,也就是系統(tǒng)正在進(jìn)行GC程序就只能阻塞住等待GC結(jié)束,在2.3之后GC操作改成了并發(fā)的方式進(jìn)行,GC過(guò)程中不會(huì)影響程序的正常運(yùn)行,但在GC操作的開始和結(jié)束還是會(huì)短暫阻塞一段時(shí)間,所以頻繁的GC會(huì)導(dǎo)致使用應(yīng)用的過(guò)程中卡頓。
??解決方案:為了應(yīng)用在使用過(guò)程中更流暢,需要盡量減少觸發(fā)GC操作,這涉及到性能優(yōu)化,對(duì)于靜態(tài)代碼的分析,AS已經(jīng)很強(qiáng)大了,可以使用Android Studio的Analyze→Inspect Code...進(jìn)行分析;

(9) TextView 的setText方法,如果傳入一個(gè)數(shù)字會(huì)直接當(dāng)作字符串資源ID處理:
??問(wèn)題現(xiàn)象:程序運(yùn)行時(shí)報(bào)“NotFoundException”異常;
??原因分析:TextView.setText(int value)的傳值有問(wèn)題,在xml文件中沒(méi)有找到id對(duì)應(yīng)的字符串;
??解決方案:給TextView設(shè)置文本的時(shí)候一定要轉(zhuǎn)成String或者Charsequence類型,避免TextView將setText中的參數(shù)當(dāng)做字符串資源ID處理,去加載字符串資源,因?yàn)樽址趚ml文件中不存在導(dǎo)致程序運(yùn)行時(shí)崩潰。

(10) 通過(guò)反射訪問(wèn)方法和字段的效率大不一樣:
??問(wèn)題現(xiàn)象:程序運(yùn)行卡、慢;
??原因分析:在一個(gè)循環(huán)中使用到了反射,并且是調(diào)用的反射方法,改成反射字段后,卡、慢的現(xiàn)象得到明顯的改善;
??解決方案:通過(guò)反射修改或者獲取類中的某個(gè)屬性時(shí),強(qiáng)烈建議使用訪問(wèn)字段的方式,不要使用訪問(wèn)方法的方式,這兩者之間的效率相差很大,親測(cè)訪問(wèn)方法是訪問(wèn)字段耗時(shí)的1.5倍,具體情況和類的復(fù)雜度有關(guān)。

(11) .nomedia文件的使用:
??問(wèn)題現(xiàn)象:程序中的緩存文件在相冊(cè)、音樂(lè)播放器中顯示;
??原因分析:相冊(cè)、音樂(lè)播放器等多媒體應(yīng)用是讀取媒體庫(kù)中的數(shù)據(jù),而程序的緩存文件被緩存到了媒體數(shù)據(jù)庫(kù)中;
??解決方案:如果你希望自己應(yīng)用生成的數(shù)據(jù)不被媒體庫(kù)掃描到,應(yīng)該在生成數(shù)據(jù)的文件夾下創(chuàng)建一個(gè)名為".nomedia"的隱藏文件,避免出現(xiàn)一些無(wú)意義的文件也被媒體庫(kù)掃描到的情況,比如APP的緩存圖片在相冊(cè)中顯示、宣傳視頻在視頻播放器中顯示、音效在音樂(lè)播放器中顯示等。

(12) 循環(huán)動(dòng)畫:
??問(wèn)題現(xiàn)象:在不待機(jī)的情況下,長(zhǎng)時(shí)間處于一個(gè)界面時(shí),手機(jī)發(fā)燙;
??原因分析:界面中存在循環(huán)動(dòng)畫,CPU、GPU一直在工作;
??解決方案:循環(huán)動(dòng)畫會(huì)導(dǎo)致界面一直在刷新,CPU、GPU持續(xù)工作,會(huì)有功耗問(wèn)題,建議拒掉這種視覺(jué)呈現(xiàn)效果。

(13) 謹(jǐn)慎使用aaptOptions.cruncherEnabled = false;
aaptOptions.useNewCruncher = false;

??問(wèn)題現(xiàn)象:編譯生成的APK文件特別大,超過(guò)了正常的大小;
??原因分析:解壓APK發(fā)現(xiàn),主要是圖片資源導(dǎo)致,將APK中的res文件夾和源碼下的res文件夾對(duì)比,發(fā)現(xiàn)多了很多圖片文件;跟蹤原因發(fā)現(xiàn)最新的buildtools對(duì)資源文件的檢測(cè)很嚴(yán)格,對(duì)于Eclipse轉(zhuǎn)AS的項(xiàng)目,很多時(shí)候都是因?yàn)閳D片問(wèn)題導(dǎo)致在AS上編譯不過(guò),比如將jpg強(qiáng)轉(zhuǎn)為png在AS上就編譯不過(guò),在項(xiàng)目中可以在build.gradle中加上這兩句:aaptOptions.cruncherEnabled = false;aaptOptions.useNewCruncher = false,屏蔽掉aapt對(duì)圖片的嚴(yán)格檢測(cè)。但需要謹(jǐn)慎使用這兩個(gè)屬性,否則可能會(huì)導(dǎo)致編譯生成的APK特別大(解壓生成后的APK發(fā)現(xiàn),對(duì)于有問(wèn)題的圖片,每個(gè)drawable文件夾下都會(huì)拷貝一份);
??解決方案:去掉屬性設(shè)置,解決編譯問(wèn)題。

3.開源項(xiàng)目中的坑##

FancyCoverFlow: 這個(gè)控件在API高于16的設(shè)備中,滑動(dòng)的過(guò)程中會(huì)強(qiáng)制刷新一遍,導(dǎo)致切換和初始化的時(shí)候都很卡,當(dāng)時(shí)覺(jué)得這個(gè)效果挺好,后來(lái)用上之后這個(gè)控件成了性能瓶頸;

FancyCoverFlow

Fresco: 這個(gè)控件用起來(lái)特別爽,唯一的缺陷的相比于相同功能的其它開源項(xiàng)目(Glide、Picasso),體積過(guò)大;

ActiveAndroid: 這個(gè)輕量級(jí)的數(shù)據(jù)庫(kù)框架也挺好用,但缺陷是初始化耗時(shí),可以看一下這篇文章:在Android中使用反射到底有多慢?

JXL: 一個(gè)讀寫Excel文件的開源庫(kù),用起來(lái)很方便,但有個(gè)問(wèn)題:文件大小超過(guò)5M直接掛掉;

JPinyin: 漢字轉(zhuǎn)拼音的一個(gè)工具庫(kù),APK加密后這個(gè)庫(kù)不能正常使用,后來(lái)查出是因?yàn)轫?xiàng)目中數(shù)據(jù)的問(wèn)題,加密后數(shù)據(jù)的內(nèi)容變化了,最后只能自己改造,將數(shù)據(jù)按照我們自己的方式處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,372評(píng)論 25 708
  • 前景提要 這篇文章是我工作中遇到的一些坑,在這里做下歸總。由于本人才疏學(xué)淺,發(fā)現(xiàn)問(wèn)題,歡迎拍磚。 系統(tǒng)API(版本...
    炚風(fēng)霽月閱讀 2,217評(píng)論 0 4
  • Android Studio JNI流程首先在java代碼聲明本地方法 用到native關(guān)鍵字 本地方法不用去實(shí)現(xiàn)...
    MigrationUK閱讀 11,953評(píng)論 7 123
  • 對(duì)于一個(gè)自認(rèn)為經(jīng)歷坎坷看透世間百態(tài)的我來(lái)說(shuō),親情友情愛(ài)情是我對(duì)各種感情的排序。人們常說(shuō)父母健在,知己兩三,...
    Ann_閱讀 397評(píng)論 0 0
  • 20170808 搞定3第二章閱讀心得 首先引用前人的兩段話,很長(zhǎng)一段時(shí)間,我一直覺(jué)得生活就要開始了,但是路上總有...
    陳一杰_阿甘歪傳閱讀 170評(píng)論 0 0