为何invalidate()不可以直接在UI线程中调用

Posted genggeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为何invalidate()不可以直接在UI线程中调用相关的知识,希望对你有一定的参考价值。

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线程中调用的主要内容,如果未能解决你的问题,请参考以下文章

invalidate和postInvalidate 的区别及使用

android中Invalidate和postInvalidate的区别

android中Invalidate和postInvalidate的差别

Android中刷新Invalidate和postInvalidate的区别

requestLayout invalidate postInvalidate

android中Invalidate和postInvalidate的区别