1. 程式人生 > >Handler: 更新UI的方法

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.

或者掃描下圖二維碼.