invalidate与postInvalidate

1、android ui操作为什么一定要在主线程中执行?

答:Android UI操作是单线程模型,关于UI更新的相关API(包括invalidate())都是按照单线程设计的,对于多线程运行时不安全的,即在非主线程调invalidate()刷新界面出现异常。所以android禁止在非主线程更新UI。

2、为什么说invalidate()是线程不安全的?
答:在非UI线程中调用invalidate会导致线程不安全,也就是说可能在非UI线程中刷新界面的时候,UI线程(或者其他非UI线程)也在刷新界面,这样就导致多个界面刷新的操作不能同步,导致线程不安全。

 

android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。 
Android提供了Invalidate方法实现界面刷新,但是不建议直接在线程中调用invalidate,建议也使用postInvalidate,排队执行。 

postInvalidate方式刷新界面是借助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();
}
}
}
 

 

posted @ 2018-11-24 22:43  庚拓天下  阅读(799)  评论(0编辑  收藏  举报