Android Crash與ANR詳細介紹
Crash
Crash是指程序閃退,導致APP不能正常使用。Crash產(chǎn)生的原因有很多,下面只是列舉了一些常見原因。
空指針
空指針應該是項目中最容易產(chǎn)生crash的情況了,舉個例子,我們獲取某個對象的屬性或方法時,這個對象為Null時,如何沒有判空,則會出現(xiàn)空指針異常NullPointException,所以這就要求使用對象的時候進行非空判斷,在這點,我覺得kotlin就做得很好,利用空安全可以很好地避免NullPointException。
角標越界
在使用數(shù)組或者集合的時候會出現(xiàn)IndexOutOfBoundsException,在根據(jù)index進行取值時,最好先判斷該索引值是否存在或者使用try-catch捕捉異常。
集合元素刪除操作
比如我們需要將集合中滿足條件的元素刪除掉
list.forEach { if (it == 3) { list.removeAt(it) } }
這樣做會引起Crash,會報ConcurrentModificationException,針對這個問題,我們可以從后面開始遍歷
for (index in list.size - 1 downTo 0) { if (list[index] == 3) { list.removeAt(index) } }
也可以使用迭代器進行遍歷刪除元素
val iterator = list.iterator() while (iterator.hasNext()) { val a = iterator.next() if (a == 3) { iterator.remove() } }
當多個線程同時操作某個數(shù)組時,不要進行數(shù)組的增刪改查等操作,這樣同樣也會引起相關(guān)的Crash或數(shù)據(jù)查詢不準確等問題。
異步操作后對界面元素的處理
在fragment中使用Context前最好先加上判斷isAdded判斷,特別是異步操作后使用Context,很有可能出現(xiàn)報錯(Fragment not attached to a context)而閃退,所有的異步回調(diào)后若要操作View,都要判斷view是否為空,否則會出現(xiàn)界面銷毀后View為空,空指針閃退問題。
Intent傳遞數(shù)據(jù)過大
Intent傳512K以下的數(shù)據(jù)可以正常傳遞,高于512K則會出錯,因為考慮到Intent還要包括要啟動的Activity等信息,所以實際可以傳的數(shù)據(jù)應該略小于512K。
val data = ByteArray(1024 * 1024) val intent = Intent(this, ExpActivity::class.java) intent.putExtra("test", data) startActivity(intent)
這段代碼會導致Crash
Caused by: android.os.TransactionTooLargeException: data parcel size 1049012 bytes
因為我們在Intent中攜帶的數(shù)據(jù)要從APP進程傳輸?shù)紸MS進程,再由AMS進程傳輸?shù)侥繕薃ctivity所在進程,普通的由 Zygote 孵化而來的用戶進程,所映射的Binder內(nèi)存大小是不到1M,但是,在使用Intent傳遞數(shù)據(jù)時,1M并不是安全上限,因為Binder可能正在處理其它的傳輸工作??偠灾瑂tartActivity攜帶的數(shù)據(jù)會經(jīng)過Binder內(nèi)核再傳遞到目標Activity中去,因為binder映射內(nèi)存的限制,所以startActivity也會這個限制。
在子線程中操作UI
子線程中是不能操作UI的,如果在子線程中某個時機想要改變UI,可以使用Handler或者kotlin協(xié)程切換,需要注意的是,在子線程中也不可以操作Dialog和Toast。但是,這有個很有意思的點,舉個例子,如果你在onCreate中開啟一個子線程改變UI,會發(fā)現(xiàn)程序運行正常,沒報錯,像這樣
class ExpActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_exp) val name = findViewById<TextView>(R.id.name) Thread { name.text = "name" }.start() } }
但是,你延遲一秒后再操作UI,又會閃退報錯
class ExpActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_exp) val name = findViewById<TextView>(R.id.name) Thread { Thread.sleep(1000) name.text = "name" }.start() } }
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
這到底是為什么呢?這個的關(guān)鍵是ViewRootImpl類,它會去檢查當前線程是不是主線程,如果不是就會拋出異常。像上面的情況,在onCreate中未延時直接操作UI不閃退,是因為此時ViewRootImpl還沒有被初始化,這個時候程序沒有去檢測當前線程是不是主線程,所以沒有拋異常。嚴格地講,在ViewRootImpl構(gòu)造的時候賦值的,賦值的就是當前的Thread對象,也就是說,你ViewRootImpl在哪個線程創(chuàng)建的,你后續(xù)的UI更新就需要在哪個線程執(zhí)行,跟是不是UI線程毫無關(guān)系。
ANR
ANR是指程序未響應,在Android系統(tǒng)中,AMS和WMS會檢測App的響應時間,如果App在特定時間無法響應屏幕觸摸或鍵盤輸入事件,或者特定事件沒有處理完畢,就會出現(xiàn)ANR。
不同Context規(guī)定的上限時間不同:
- 主線程對輸入事件5秒內(nèi)沒有處理完畢。
- 主線程在執(zhí)行BroadcastReceiver的onReceive()函數(shù)時10秒內(nèi)沒有處理完畢。
- 主線程在Service的各個生命周期函數(shù)時20秒內(nèi)沒有處理完畢。
避免ANR就要盡量避免在主線程中做耗時操作,耗時操作盡量放在子線程中。
我們可以通過/data/anr/traces.txt文件來分析ANR的產(chǎn)生,通過adb命令可以導出該文件,不過traces文件記錄的東西可能比較多,分析的時候需要針對性地搜索出相關(guān)記錄,該文件會記錄進程ID,包名,造成ANR的原因和產(chǎn)生ANR的具體行數(shù)。
到此這篇關(guān)于Android Crash與ANR詳細介紹的文章就介紹到這了,更多相關(guān)Android Crash與ANR內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android中利用zxing實現(xiàn)自己的二維碼掃描識別詳解
這篇文章主要給大家介紹了關(guān)于Android中利用zxing實現(xiàn)自己的二維碼掃描識別的相關(guān)資料,文中通過圖文介紹的非常詳細,對大家學習或者使用zxing具有一定的參考學習價值,需要的朋友們下面來一起看看吧。2017-09-09Android批量插入數(shù)據(jù)到SQLite數(shù)據(jù)庫的方法
這篇文章主要為大家詳細介紹了Android批量插入數(shù)據(jù)到SQLite數(shù)據(jù)庫的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03Android 使用 ViewPager循環(huán)廣告位的實現(xiàn)
本文給大家分享android使用 ViewPager循環(huán)廣告位的實現(xiàn),感興趣的朋友一起學習吧2015-11-11Android 正則表達式驗證手機號、姓名(包含少數(shù)民族)、身份證號
本篇文章主要介紹了Android 正則表達式驗證手機號、姓名(包含少數(shù)民族)、身份證號的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04Android開發(fā)之圖形圖像與動畫(四)AnimationListener簡介
就像Button控件有監(jiān)聽器一樣,動畫效果也有監(jiān)聽器,只需要實現(xiàn)AnimationListener就可以實現(xiàn)對動畫效果的監(jiān)聽,感興趣的朋友可以了解下啊,希望本文對你有所幫助2013-01-01Java4Android開發(fā)教程(二)hello world!
一般的開發(fā)教程都是介紹完安裝配置開發(fā)環(huán)境,緊接著來一篇hello world,算是國際慣例吧,我們當然也不能免俗,哈哈,各位看官請看好了!2014-10-10