子執行緒為什麼可以更新UI操作,那是因為

2021-08-19 00:13:56 字數 2113 閱讀 9453

子執行緒中真的不可以更新ui麼?

看乙個熟悉的場景:

執行結果可能很多人猜是:viewrootimpl$calledfromwrongthreadexception

可惜啊,並沒有任何異常,良好執行。

這個不是有悖我們原則麼?  

你們這麼想就是誤解了這個原則,原話是不推薦在子執行緒中更新ui,因為會造成不必要的錯誤,沒說不行啊。

那麼calledfromwrongthreadexception出現在**呢?

但是上面的**顯然沒有執行到這個方法(這個方法在哪找,請接著向下看),也就不會有異常發生。

接下來就是解析這個settext方法,看它在什麼情況可以執行到checkthread方法,什麼時候又不可以

檢視textview方法呼叫順序

最後呼叫到了最後乙個settext(charsequence,textview,buffertype,boolean,int)

方法裡找到關鍵**:

checkforlayout方法 :檢查是否這個新的文字需要乙個新的view物件或僅僅是乙個新的布局(layout)

檢視checkforlayout方法,裡面有一段關鍵**

兩種情況下都需要呼叫requestlayout方法,這個方法可以改變並應用view的自身大小和自身位置

這個方法是textview父類view的方法:

看到下面有一行 mparent.requestlayout(); 

這裡也有乙個requestlayout方法,呼叫者是mparent,這個mparent是viewparent的物件,但是viewparent是介面,

view在assignparent中給mparent物件賦值,檢視誰呼叫了這個方法,追溯到了viewrootimpl

viewrootimpl物件呼叫了view.assignparent(this);傳入了自身

則mparent.requestlayout就是viewrootimpl中的方法

在這裡進行執行緒檢查,但是為什麼一開始的程式沒有執行到這呢,因為在oncreate中,activity還未建立viewrootimpl物件,

mparent = null 為true

這裡沒有去繼續探尋activity什麼時候建立這個viewrootimpl,

做個測試:

加1000ms的延遲再去更新ui,這個時候就出現了crash,可以推測因為viewrootimpl已經被建立,可以進行執行緒的檢查了

最後總結一下子執行緒更新ui的正確姿勢:

1;使用handler  

2;使用activity的runonuithread方法把更新ui的**建立在runnable中即可

3;使用asynctask

三種方法**都很簡單,就不貼了。。。

子執行緒更新UI

一般在winform c s程式中經常會在子執行緒中更新控制項的情況,桌面程式ui執行緒是主線程,當試圖從子執行緒直接修改控制項屬性時會出現 從不是建立控制項的執行緒訪問它 的異常提示。跨執行緒更新ui控制項的常用方法有兩種 1.使用控制項自身的invoke begininvoke方法 2.使用sy...

為什麼 Android 更新 UI 只能在主線程

ui訪問沒有加鎖,在多個執行緒訪問ui是不安全的。所以android中規定只能在ui執行緒中訪問ui。一些朋友說在 oncreate 中 可以 建立子執行緒操作 ui,不會程式崩潰 網上已有很多人分析過 主要是因為 1.錯誤是從 viewrootimpl.requestlayout viewroot...

Qt子執行緒如何更新UI?

和其他語言類似,不能直接在子執行緒更新ui,可以通過signal slot機制在ui執行緒進行更新。signal slot機制可以在不同物件,不同執行緒之間進行通訊。例子 include mainwindow.h include include class mythread public qthre...