day 17 面試題:Handler相關

面試題:

Handler相關
1. 談談Handler消息機制,有什麼作用,有哪些要素,流程是怎樣的?
2. 爲什麼系統不建議在子線程訪問UI?
3. 一個Thread可以有幾個Looper?幾個Handler?
4. 如何將一個Thread線程變成Looper線程?Looper線程有哪些特點?
5. 可以在子線程直接new一個Handler嗎?怎麼做?
6. Message可以如何創建,哪種效果最好?爲什麼?
7. 這裏的ThreadLocal有什麼作用?
8. 主線程中的Looper的輪詢死循環爲何沒有阻塞主線程?
9. 使用Handler的postDealy()後消息隊列會發生什麼變化?

1. 談談Handler消息機制,有什麼作用,有哪些要素,流程是怎樣的?

此節參考我另一篇文章,寫的是Handler的工作流程和關鍵對象間的關係的。

2. 爲什麼系統不建議在子線程訪問UI?

標準回答

首先UI控件是線程不安全的,如果多線程併發訪問UI控件可能出現不可預期的狀態

那爲什麼不對UI控件加上鎖呢?

  1. 加鎖會讓UI訪問的邏輯變得更加複雜
  2. 鎖機制會降低UI訪問的效率,因爲鎖會阻塞某些線程

鑑於以上幾點,安卓的UI訪問採用單線程模式來處理。如果在非UI線程訪問UI會拋出CalledFromWrongThreadException異常。

3. 一個Thread可以有幾個Looper?幾個Handler?

由於使用了ThreadLocal機制,所以註定了一個線程只能有一個Looper,但Handler可以new無數個。

4. 如何將一個Thread線程變成Looper線程?Looper線程有哪些特點?

經過如下3個步驟就可以將一個線程變成Looper線程,無參構造創建的Handler是和當前線程的Looper綁定的。

Looper.prepare();
Handler handler = new Handler();
Looper.loop();

looper線程跟普通線程不一樣的是可以使用Handler進行傳遞消息。

5. 可以在子線程直接new一個Handler嗎?怎麼做?

  1. 如果是子線程的Handler,看上一個步驟中的邏輯

  2. 如果是創建主線程的Handler,則需要傳入MainLooper

     Handler mainHandler = new Handler(Looper.getMainLooper());
    

6. Message可以如何創建,哪種效果最好?爲什麼?

創建Message的三種方式:

Message message = Message.obtain();
Message message = handler.obtainMessage();
Message message = new Message();

前兩種都是從消息池中返回一個新的實例,能有效避免重複創建Message。

7. 這裏的ThreadLocal有什麼作用?

主要用來存儲Looper,保證Looper的唯一性。

8. 主線程中的Looper的輪詢死循環爲何沒有阻塞主線程?

主線程其實就是一個默認實現了Looper的無限循環的線程,而各個需要在主線程執行的邏輯都會通過Handler來處理,MessageQueue中沒有Message的時候,線程是不會卡住的,因爲什麼也沒有執行。而主線程在處理UI的操作或者Activity的生命週期在執行時,如果超過一定時間就會報ANR。

9. 使用Handler的postDealy()後消息隊列會發生什麼變化?

postDelay的Message並不是等待一段時間再放入MessageQueue,而是將當前Message的delay時間和隊頭的Message比較,按照觸發時間進行排序,到對應時間再喚醒並執行Message。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章