Handler: 更新UI的方法
總是感覺 android 中 UI 更新很讓人糾結!自己小結一下,算是拋磚引玉。讀這篇文章之前,假設你已經明白執行緒、Handler 的使用。
在文章的最後,附錄一張草圖,主要用於說明 Handler、Message、MessageQueue、Looper 之間的關係。
1. 在 onCreate() 方法中開啟執行緒更新 UI
隨便折騰,不會報錯或者異常!
以為開啟的執行緒和 UI 執行緒(主執行緒)是同一個執行緒,但是很不幸,他們的執行緒id根本是風牛馬不相及!
大家可以跟蹤一下android 原始碼,這個主要是因為在載入 Activity 的時候,還沒有觸發檢查單執行緒的模型(即子執行緒不可以更新ui)。
如果你不相信的話,可以在上面的執行緒裡面 while true,那麼一定會報錯的。
2. 在 activity 如 onResume、onStart、反正是以 on 開頭的回撥方法
不好意思,按下返回按鈕在啟動程式,或者按 Home 鍵再啟動程式,就這麼折騰幾下,就會包異常!資訊如下:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
意思是:只有主執行緒才可以更新 UI。
解決辦法:加上 postInvalidate() 方法。
postInvalidate() 方法,原始碼:
其實,是呼叫了 Handler 的處理訊息的機制!該方法可以在子執行緒中直接用來更新UI。還有一個方法 invalidate(),稍候再說!
3. 在 Button 的事件中開啟執行緒,更新 UI
Sorry,報錯!即使你加上 postInvalidate() 方法,也會報這個錯誤。
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
4. 使用 Handler 結合多執行緒更新 UI a. 開啟一個執行緒,在 run 方法中通知 Handler b. Handler 中使用 handleMessage 方法更新 UI。 5. Handler 和 invalidate 方法結合多執行緒更新 UI 方法 invalidate 主要用在主執行緒中(即UI 執行緒中),不可以用於子執行緒。如果在子執行緒中需要使用 postInvalidate 方法。 sdk 的 api 有說明: 看看該方法原始碼: invalidate 方法如果你直接在主執行緒中呼叫,是看不到任何更新的。需要與Handler結合! 只是被我修改了一點,加入times,看看 onDraw 到底執行多少次。
Android 在 onDraw 事件處理繪圖,而 invalidate() 函式可以再一次觸發 onDraw 事件,然後再一次進行繪圖動作。
經過測試,發現 times 一直在++,說明 onDraw 被多次呼叫,並且一致在畫圖!
SDK 的 API 有時候讓人很鬱悶,無語.....關於 invalidate 的使用,還待探索。革命尚未成功,同志仍需努力!
部落格更新,推薦文章:
附錄: Handler、Message、MessageQueue、Looper 之間的關係
這裡說明
1. Looper 使用無限迴圈取出訊息,是有 android os 控制的。
2. android 執行緒是非安全的,即不要在子執行緒中更新 UI。
3. Looper 取出來的訊息,handler 可以通過 what、obj 等量來區別分別獲取屬於自己的訊息,所以推薦使用這些量。
歡迎大家關注我的個人微信公眾號: ITMan, 微信公眾號搜尋: ITManMark.
或者掃描下圖二維碼.