首先 先 明白一個問題:什么是ANR
Application Not Responding,意思是”應(yīng)用沒有響應(yīng)“
以前我的理解就是 “在主線程做了耗時操作”就會引起ANR,現(xiàn)在我覺得我是錯誤的,ANR的意思是應(yīng)用沒有響應(yīng),耗時操作實際上 并不一定會導(dǎo)致沒有響應(yīng),我對沒有響應(yīng)的理解是
有人(事件或操作)發(fā)出了一個請求,但是主線程沒有對這個人進行反饋(可能是沒時間、可能是不想理、可能是手被綁住了沒有辦法理你),這個叫沒有響應(yīng)
那舉個例子
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// do some blablabla...
Log.d("test", "準(zhǔn)備sleep30秒")
Thread.sleep(30000)
Log.d("test", "sleep30秒完成")
// do some blablabla...
}
這段代碼在 onCreate 中 sleep 了 30秒,會出現(xiàn) ANR 嗎?
答案是
可能會,也可能不會
當(dāng)主線程在 Sleep 的時候,如果 UI線程不需要進行操作,也就是說沒有消息會發(fā)送給UI線程并要求UI線程進行處理的時候 Sleep 30秒就不會導(dǎo)致ANR,因為沒有 出現(xiàn) ANR(應(yīng)用沒有響應(yīng))的情況啊,沒有人向線程請求什么東西,也就不需要響應(yīng)了,既然沒有響應(yīng)了,那怎么會有ANR呢?
但是,但線程在Sleep的時候,主線程有接收到需要處理的請求的時候
需要注意的是,需要處理的請求,不一定只是用戶的手動觸摸,也有可能是其他線程需要對線程進行UI更新的請求,這個時候UI線程正在Sleep,根本沒有辦法理你(不想理你),這就符合了ANR的條件,所以會出現(xiàn)ANR(比如說在這 30 秒內(nèi),點擊了 返回按鈕,就會出現(xiàn) ANR)
另外,如果在這個30秒內(nèi)進行UI更新會發(fā)生ANR嗎?
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Handler().postDelayed(Runnable {
Log.d("sleep_test", "準(zhǔn)備更新text")
btn_test.text = "update btn text"
Log.d("sleep_test", "更新text完成")
}, 10000)
Log.d("sleep_test", "準(zhǔn)備sleep30秒")
Thread.sleep(30000)
Log.d("sleep_test", "sleep30秒完成")
Log.d("sleep_test", "first update")
btn_test.text = "This is the first update"
}
輸出結(jié)果為:
D/sleep_test: 準(zhǔn)備sleep30秒
D/sleep_test: sleep30秒完成
D/sleep_test: first update
D/sleep_test: 準(zhǔn)備更新text
D/sleep_test: 更新text完成
并沒有發(fā)生ANR,這是因為這段代碼里面的sleep休眠了線程,代碼里面的更新操作根本沒有在 sleep的時候被觸發(fā)(處于休眠狀態(tài)),也就沒有了發(fā)送請求的前提條件,所以并沒有發(fā)生ANR。但是如果用戶手動進行了觸摸操作,相當(dāng)于有一個請求的事件了,而主線程又被休眠了,超過了規(guī)定的時間就會觸發(fā)ANR提示
在android里面都對其進行了常量定義
Android N 的 ANR時間
- Service 超時
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000; // 前臺
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // 后臺
- Broadcast 超時
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000; // 前臺
static final int BROADCAST_BG_TIMEOUT = 60*1000; // 后臺
- InputDispatching 超時
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
- ContentProvider 超時
// How long we wait for an attached process to publish its content providers
// before we decide it must be hung.
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
ANR的學(xué)習(xí)目前就到這個點,后續(xù)還要繼續(xù)學(xué)習(xí)
延伸:Thread.sleep() 還有其加鎖的問題
由于CPU分配的每個線程的時間片極為短暫(一般為幾十毫秒),所以,CPU通過不停地切換線程執(zhí)行,這樣就給程序員一種錯覺,以為多個線程是在同時執(zhí)行。sleep就是正在執(zhí)行的線程主動讓出CPU,CPU去執(zhí)行其他線程,在sleep指定的時間過后,CPU才會回到這個線程上繼續(xù)往下執(zhí)行。
已發(fā)布至: jimbray