1.ANR有哪幾種?
從ActivityManagerService的實現可以看到,ANR有四種,分別對應Android的四個fundermetals。這個也不難理解:所有fundermetal都會在main thread上運行,如果超過了響應的間隔,那麼就會ANR。另外JNI調用native函數時也會發生無響應,不過我覺得應該不算單獨的一種,它只是未響應發生在了native裏,而不是vm裏。
2.ANR是什麼?
從ActivityManagerService可以看到,作爲一個manager類,要去檢測所管理的對象是否處於可相應狀態,一個不錯的方式就是給那個對象發消息,並等待回調。事實上,就是這麼做的。每隔一段時間,manager會發消息給所有fundamental,這個消息格式固定,同時帶一個delay time,譬如說activity的delay time就是5000ms,當消息發出之後,5000ms之內沒有收到相應,那麼manager就要把那個activity ANR掉。對於broadcast receiver、provider和service也是同樣的,只是delay time不一樣。
以Activity爲例,幾個負責Activity生命週期的回調方法(以on開頭的那幾個),被調用後,5000ms內沒有返回,那麼就ANR鳥。另外還有key dispatch ANR,也就是說,當用戶點擊了進行了某些操作產生key event了,那麼應用就必須在規定時間處理key event,如果超時,會立刻ANR。
3.ANR的導致原因
我敘述一下google I/O 2010上一個presentation上說的:就是性能問題。我們知道,一般情況下,Android系統的瓶頸經常在I/O操作,無論是本地還是網絡,經常會導致程序看起來不那麼順暢,如果達到某個時間沒有響應,那麼就ANR鳥。我猜測,
4.如何避免ANR
"Never never never do slow things on main thread".我引用了那個presentation的原話。
5.如何解決ANR的問題
上面介紹了ANR的一些基本知識,但是在現實問題中,ANR的問題經常會比較難解決。而且每一種ANR在logcat的信息中都會有不同的。如果要了解不同ANR的特點,就需要些多個實例來觀察log信息。這裏需要關注的幾個信息是,線程、內存、CPU、異常堆棧等信息。google貌似提供了工具來dump發生ANR時的系統及APP信息。