1. 程式人生 > >為何invalidate()不可以直接在UI線程中調用

為何invalidate()不可以直接在UI線程中調用

pub 什麽 安全 調用 inter 開始 都是 android while

1、android ui操作為什麽一定要在主線程中執行?

答:Android UI操作是單線程模型,關於UI更新的相關API(包括invalidate())都是按照單線程設計的,對於多線程運行時不安全的,即在非主線程調invalidate()刷新界面出現異常。所以android禁止在非主線程更新UI。

2、為什麽說invalidate()是線程不安全的?
答:在非UI線程中調用invalidate會導致線程不安全,也就是說可能在非UI線程中刷新界面的時候,UI線程(或者其他非UI線程)也在刷新界面,這樣就導致多個界面刷新的操作不能同步,導致線程不安全。


3、為何invalidate()不可以直接在UI線程中調用?
答:Android主線程的執行,是通過Looper循環調度消息的機制運行的;主線程一直在執行Looper循環中,更新UI需要通過Handler往消息隊列發送消息,Looper調度到以後便可以執行invalidate()。


android中實現view的更新有兩組方法,一組是invalidate,另一組是postInvalidate,其中前者是在UI線程自身中使用,而後者在非UI線程中使用。
Android提供了Invalidate方法實現界面刷新,但是Invalidate不能直接在線程中調用,因為他違背了Android UI操作的單線程模型。

invalidate方式刷新界面需要借助handler發送消息給UI線程,排隊輪到時,收到刷新指令,才調用invalidate()開始刷新

postInvalidate方式底層的實現,是和上述invalidate方式一樣的,借助於handler發送消息。源碼參考https://blog.csdn.net/ziwang_/article/details/65690751

// 在onCreate()中開啟線程
 
new Thread(new GameThread()).start();、
 
// 實例化一個handler
 
Handler myHandler = new Handler() {
// 接收到消息後處理
public void handleMessage(Message msg) {
switch (msg.what) {
case Activity01.REFRESH:
mGameView.invalidate(); // 刷新界面
break;
}
 
super.handleMessage(msg);
}
};
 
class GameThread implements
Runnable { public void run() { while (!Thread.currentThread().isInterrupted()) { Message message = new Message(); message.what = Activity01.REFRESH; // 發送消息 Activity01.this.myHandler.sendMessage(message); try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }
class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
 
// 使用postInvalidate可以直接在線程中更新界面
mGameView.postInvalidate();
}
}
}
 

為何invalidate()不可以直接在UI線程中調用