android死循環
1. Android-Looper
Looper.loop是一個死循環,拿不到需要處理的Message就會阻塞,那在UI線程中為什麼不會導致ANR?
首先我們來看造成ANR的原因:
1.當前的事件沒有機會得到處理(即主線程正在處理前一個事件,沒有及時的完成或者looper被某種原因阻塞住了)
2.當前的事件正在處理,但沒有及時完成
我們再來看一下APP的入口ActivityThread的main方法:
顯而易見的,如果main方法中沒有looper進行死循環,那麼主線程一運行完畢就會退出,會導致直接崩潰,還玩什麼!
現在我們知道了消息循環的必要性,那為什麼這個死循環不會造成ANR異常呢?
我們知道Android 的是由事件驅動的,looper.loop() 不斷地接收事件、處理事件,每一個點擊觸摸或者說Activity的生命周期都是運行在 Looper的控制之下,如果它停止了,應用也就停止了。只能是某一個消息或者說對消息的處理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它,這也就是我們為什麼不能在UI線程中處理耗時操作的原因。
主線程Looper從消息隊列讀取消息,當讀完所有消息時,主線程阻塞。子線程往消息隊列發送消息,喚醒主線程,主線程被喚醒只是為了讀取消息,當消息讀取完畢,再次睡眠。因此loop的循環並不會對CPU性能有過多的消耗。
初始化當前線程和Looper,這樣可以在實際開始啟動循環(loop())之前創建一個Handler並且關聯一個looper。確保在先調用這個方法,然後調用loop()方法,並且通過調用quit()結束。
這裡面的入參boolean表示Looper是否允許退出,true就表示允許退出,對於false則表示Looper不允許退出。
初始化當前當前線程的looper。並且標記為一個程序的主Looper。由Android環境來創建應用程序的主Looper。因此這個方法不能由咱們來調用。另請參閱prepare()
這里的sThreadLocal.get()是和prepare(boolean)方法裡面的sThreadLocal.set(new Looper(quitAllowed));一一對應的。而在prepareMainLooper()方法裡面。
退出循環
將終止(loop()方法)而不處理消息隊列中的任何更多消息。在調用quit()後,任何嘗試去發送消息都是失敗的。例如Handler.sendMessage(Message)方法將返回false。因為循環終止之後一些message可能會被無法傳遞,所以這個方法是不安全的。可以考慮使用quitSafely()方法來確保所有的工作有序地完成。
安全退出循環
調用quitSafely()方法會使循環結束,只要消息隊列中已經被傳遞的所有消息都將被處理。然而,在循環結束之前,將來不會提交處理延遲消息。
調用退出後,所有嘗試去發送消息都將失敗。就像調用Handler.sendMessage(Message)將返回false。
2. 用eclipse做android,每次運行的時候都是這個錯,而且還死循環,幫我解決一下啊
你的原因是:主板的BLOS信息因為一些軟體安裝處於不確定狀態,開機的時候選擇F1鍵會進入藍屏狀態的華碩blos設置界面,其實裡面的參數不需要修改,只需要按一下,F10鍵(F10是保存BLOS的設置信息)然後它會提示你是否保存,選擇YES。就可以了,以後開機就不會出現這個問題了。祝樓主好運。
3. 安卓按鍵精靈死循環如何解救
先看一下"行數"是多少,是不是有空白行沒有算進去
4. android從寫onDraw為什麼進入了死循環
this.postInvalidate();
這條語句的含義是在子線程中通知UI線程強制更新,而你的類是View類型,其更新的含義就是重繪這個界面,也就是說不停的調用了onDraw()這個方法繪制界面。
所以我建議朋友你梳理下業務邏輯,加入判斷進行控制。
望採納,謝謝~~
5. android後退鍵進入死循環,第一個頁面後退到第二個,第二個後退又到第一個.求教,謝謝
看了你下面的代碼、目測你這個問題應該不是經常出現、之所以會出現 應該是你退出程序的時候只關閉了第一個activity、 第二個 activity、
還是打開的,那麼你多次重復進入 就會有多個第二個頁面、可能你第二個頁面又有跳轉到第一個頁面的代碼這就導致了第一個頁面每次都關閉 第二個頁面關閉不了,病跳轉到第一個頁面 第一個又關閉。。。。 死循環了,解決這個問題你可以在第二個頁面加入xxxxactivity。this,finish(); OK 應該就是這樣
6. android 子線程中的死循環怎麼設置
設置標記變數,while(isValid){}
如果想退出的時候,將isValid置為false
7. Android中為什麼主線程不會因為Looper.loop里的死循環卡死
Handler類怎麼會算線程呢,它是用來發送和處理消息用的,而Looper類是用來存儲消息隊列以及處理消息循環的一個封裝類。 UI線程本身已經實現了消息隊列,所有可以直接創建Handler類 而自己創建的線程要實現消息處理,必須調用Looper.prepare()來創建消息隊列以及其他一些步驟的初始化,再創建Handler,最後調用Looper.loop()實現消息循環
8. android程序鎖問題(程序鎖進入死循環)
沒看懂。。。
9. Android-保活
Low Memory Killer
打開的應用越多,後台緩存的進程也越多。因為系統出於體驗和性能上的考慮,app在退到後台時系統並不會真正的kill掉這個進程,而是將其緩存起來。於是在系統內存不足的情況下,系統開始依據自身的一套進程回收機制來判斷要kill掉哪些進程,以騰出內存來供給需要的app, 這套殺進程回收內存的機制就叫 Low Memory Killer。
進程的優先順序(by:https://developer.android.google.cn/guide/components/activities/process-lifecycle?hl=zh-cn)
前台進程
用戶正在使用的程序,一般系統是不會殺死前台進程的,除非用戶強制停止應用或者系統內存不足等極端情況會殺死。
可見進程
用戶正在使用,看得到,但是摸不著,沒有覆蓋到整個屏幕,只有屏幕的一部分可見進程不包含任何前台組件,一般系統也是不會殺死可見進程的,除非要在資源吃緊的情況下,要保持某個或多個前台進程存活施。
服務進程
在內存不足以維持所有前台進程和可見進程同時運行的情況下,服務進程會被殺死。
後台進程
系統可能隨時終止它們,回收內存。
空進程
某個進程不包含任何活躍的組件時該進程就會被置為空進程,完全沒用,殺了它只有好處沒壞處,第一個干它。
內存閾值
內存閾值在不同的手機上不一樣,一旦低於該值,Android便會殺死對應優先順序的進程。一旦低於該值,Android便開始按逆序關閉進程。即優先順序從最高的空進程開始,逆序關閉,直到內存足夠。
如何判斷進程的優先順序?
通過 oom_adj 值,判斷進程的優先順序,不同手機的oom_adj 值可能不一樣。
我們了解這個有什麼用呢?PS:了解這個你才能想辦法保證自己怎麼不被殺掉。
網上的一些方案和自己認為有用的方案
1 開啟一個像素Activity(偽前台進程)
在鎖屏的時候在本進程開啟一個Activity,為了欺騙用戶,讓這個Activity的大小是1像素,並且透明無切換動畫,在開屏幕的時候,把這個Activity關閉掉,所以這個就需要監聽系統鎖屏廣播。
我們的應用就始終和前台進程是一樣的優先順序了,為了省電,系統檢測到鎖屏事件後一段時間內會殺死後台進程,如果採取這種方案,就可以避免了這個問題,但是還是有被殺掉的可能。
Android5.0以下:
Process.killProcessQuiet(pid);
Android5.0以後:
Process.killProcessQuiet(app.pid);
Process.killProcessGroup(app.info.uid, app.pid);
應用退出後,ActivityManagerService不僅把主進程給殺死,另外把主進程所屬的進程組一並殺死,這樣一來,由於子進程和主進程在同一進程組,子進程在做的事情,也就停止了。
2 相互喚醒(廣播喚醒)
相互喚醒的意思就是,假如你手機里裝了支付寶、淘寶、天貓、UC等阿里系的app,那麼你打開任意一個阿里系的app後,有可能就順便把其他阿里系的app給喚醒了。這個完全有可能的。此外,開機,網路切換、拍照、拍視頻時候,利用系統產生的廣播也能喚醒app,不過Android N已經將這三種廣播取消了。
3 JobSheler機制保活(不推薦)
JobSheler是作為進程死後復活的一種手段,native進程方式最大缺點是費電, Native 進程費電的原因是感知主進程是否存活有兩種實現方式,在 Native 進程中通過死循環或定時器,判斷主進程是否存活,當主進程不存活時進行拉活。其次5.0以上系統不支持。 但是JobSheler可以替代在Android5.0以上native進程方式,這種方式即使用戶強制關閉,部分廠商手機(如:華為)也能被拉起來,但AndroidN失效。
4 粘性服務&與系統服務捆綁()
這個是系統自帶的,onStartCommand方法必須具有一個整形的返回值,這個整形的返回值用來告訴系統在服務啟動完畢後。Service的onStartCommand方法里返回 STATR_STICK,onDestory中start自啟(准確的將算不上進程拉活,只能算service自啟,force_stop後不能正常拉活)。
5 監聽第三方app開放的靜態廣播(同2)
需要大量反編譯app去找開放的靜態廣播,而且不保證長期有效,可能第三方開放廣播在版本升級時改為私有廣播,如果自己公司有多個app,可廣播互相拉起。
6 NDK+Socket通過fork實現進程保活方案()
實現進程守護實際是守護app的主要服務,當app主進程被系統kill時,主要服務也會殺死,守護進程將其喚醒。
實現原理圖:
進程保活方案調研結果
未能實現真正意義上的進程保活。
光從保活這一點來說,綁定一個像素activity和循環一個無聲的聲音這種方法比較好,但是對用戶來說太流氓了,不推薦。 對於有硬性需求的,可以引導用戶加入白名單。至於推送, 可以嘗試集成多個推送方案,小米,華為等都有推送sdk,在對應手機上可以確保收到消息, 然後像網路這種是多app公用通道的,也就是手機中有一個使用網路推送的app被允許後台啟動,就能讓其他app收到推送。隨著Android版本的不斷更新及國內廠商對ROM的不斷優化,如何最大可能的對進程保活,是Android一道需要長期學習/鑽研的學問,也是Android開發者不得不面對的問題。
引援:https://www.jianshu.com/p/1c353edf73ba
10. Android Handle中Looper.loop()的死循環為什麼在主線程中不會產生卡死現象
1. 主線程,負責一些UI更新操作,歸類為一個線程,線程在Android中是有生命周期的,任務最終是會結束的。
2. Looper.loop()的死循環正是維護了主線程的超長生命周期,loop方法一直循環處理任務,沒有任務的時候會休眠,有任務的時候會喚醒然後進行處理,所以也不會佔用太多系統資源。
3. 卡死,可能有誤解,循環的過程中本生不會出現ANR,在循環的過程中,如果執行了耗時且在規定時間內沒有完成消息派發,才會出現ANR。