runOnUiThread在主線程更新UI

2021-09-12 09:24:26 字數 2633 閱讀 6264

在主線程中更新ui,一般有兩個方法,使用handle和runonuithread的方法

1. 使用handle的方法更新ui

2. 使用runonuithread更新ui

activity.this. runonuithread(new runnable() 

});

3. 原碼分析

在android開發的過程中,主線程主要來完成ui繪製和響應使用者的操作,預設情況下,我們大部分的**都是在主線程 

中執行的,因此我們時刻要考慮主線程的情況。我們都知道要開啟乙個子執行緒來完成乙個耗時操作,以避免阻塞主線程影響 

使用者體驗,甚至anr。但是子執行緒執行完要更新ui的時候,我們又必須回到主線程來更新,實現這一功能常用的方法是執行 

activity的runonuithread()方法:

runonuithread(new runnable()

});這樣就可以很神奇的使run()中的方法在主線程中執行。那麼runonuithread()是怎麼使run()中的**在主線程中執行的呢?

開始分析

先從activity的部分原始碼開始:

final handler mhandler = new handler();

private thread muithread;

// ...

public final void runonuithread(runnable action) else

// ...

}**很簡單,首先判斷當前的執行緒是否是主線程,如果是住執行緒就直接執行runnable介面的run()方法;但如果不是主線程 

呢?這時呼叫handler的post(runnable)方法。那麼這個過程又發生了什麼了呢?讓我們從looper說起。

looper

我們建立乙個執行緒並重寫它的run()方法,如下:

public class mythread extends thread

}當這個run()方法中的語句執行完的時候,這個執行緒就結束了,無用了。如果我們為了減小記憶體而不建立新的執行緒來復用 

這個執行緒的時候,我們需要它保持存活並等待新的指令。常見的做法是建立乙個迴圈:

public class mythread extends thread }}

只要while迴圈沒執行完,執行緒就保持存活。這就是looper可以實現的,looper字面意思就是「迴圈」,保持執行緒存活。 

關於looper值得一提的事: 

* 執行緒預設不會得到looper; 

* 可以再執行緒中建立乙個looper; 

* 每個執行緒只能建立乙個looper。 

下面我們用looper替換white迴圈:

public class mythread extends thread

}呼叫looper.prepare()檢查當前執行緒中是否有looper,如果沒有則建立。呼叫looper.loop()後looper開始迴圈。 

這樣,looper迴圈並保持執行緒存活,但這樣什麼也不做的執行緒存活是沒有意義的。 

當建立looper時,它建立了乙個訊息佇列(messagequeue),用來存放訊息(message)。

什麼是訊息

message實際上就是一些指令的集合。它能保持string,int,runnables等資料型別。 

如果我們想要在特定的執行緒執行runnables,我們只需將runnables放到訊息中,並將訊息放到這個執行緒的looper建立 

的訊息佇列中!那麼如何放到訊息佇列中呢?又用到了handler。

handler

handler就是處理者的意思,他負責將訊息放到looper的訊息佇列中,當到了執行的時候,他又負責在looper所繫結的 

執行緒中執行這個訊息。 

handler被建立的時候是指向特定的looper的。有兩種不同的建立方式:

1. 在構造方法中指定looper:

handler handler = new handler(looper looper); 

2. 使用空構造方法,此時指向當前執行緒的looper:

handler handler = new handler(); 

handler能非常便利的建立訊息並將其新增到looper的訊息佇列末尾,如post()。 

所以,我們只需將runnable傳到post()中:

handler.post(new runnable() 

});是不是看上去很眼熟了。

結論重新回過頭來看runonuithread()的原始碼:

final handler mhandler = new handler();

private thread muithread;

// ...

public final void runonuithread(runnable action) else

// ...

}首先在主線程裡通過無參的構造方法建立乙個handler,這個handler是指向主線程的。 

當執行runonuithread()時,當前執行緒不是主線程,呼叫mhandler.post(action),將runnable新增到主線程的訊息佇列中 

這樣,runnable的語句就是在主線程執行的了。

--------------------- 

原文: 

runOnUiThread簡單應用

首先runonuithread是activity內部的方法,在運用的時候最好指明當前環境變 context new thread new runnable start new thread new runnable start 上面兩個其實原理一樣,runonuithread這個會呼叫父類中的 pu...

visual studio在主工程中匯入靜態庫工程

又他媽的乙個上午浪費到這樣乙個無意義的事情中了。需求 我需要將別人的vs工程匯入到自建的工程檔案中,就是已經獲取了別人的vs工程的原始碼,要把它當做乙個靜態庫使用。這個問題,可能太簡單,以至於網上在這裡語焉不詳。本人是使用vs的小白,今天才開始用,且是情非得已。平時,用這麼大的ide,有必要嗎。這個...

在主函式內使用巨集定義

之前習慣於在主函式外面使用巨集定義,但實際上主函式內也可使用,例 include include include include include include intmain define min x,y x y x y char const end ptr g 8 char tmp ptr g ...