简述invalidate()和postInvalidate()方法的区别和应用场景?
在Android开发中,invalidate()
和 postInvalidate()
都是 View
类中用于请求重新绘制视图的方法,但它们的使用场景和执行方式存在差异。理解这两个方法的区别对于管理和优化UI渲染是非常重要的。
invalidate()
- 功能:
invalidate()
方法是用来告诉系统视图的某个区域需要被重绘。调用这个方法会导致视图在未来某个时刻重新调用其onDraw()
方法。 - 调用线程:
invalidate()
方法必须在UI线程(主线程)上调用。如果在工作线程中直接调用invalidate()
,程序会抛出异常,因为UI的重绘不能在非UI线程直接操作。 - 应用场景:当视图的状态发生变化且需要更新显示时,且确定当前在主线程上,可以直接调用此方法。例如,在触摸事件或属性动画中改变了视图的某个属性后,可以调用
invalidate()
来更新视图。
postInvalidate()
- 功能:
postInvalidate()
与invalidate()
功能相同,都是用于请求重绘视图,但它特别适用于非UI线程。 - 调用线程:
postInvalidate()
可以在任何线程中调用,它内部会将重绘操作委托给UI线程处理,因此不会有线程安全的问题。 - 应用场景:当在一个工作线程中需要更新视图(如在进行网络操作后需要更新UI显示结果),就需要使用
postInvalidate()
来确保UI的正确更新。
示例
假设你在一个自定义视图中根据下载进度绘制一个进度条,进度的更新在一个工作线程中进行:
class CustomView extends View {
private float progress = 0;
public CustomView(Context context) {
super(context);
}
public void setProgress(float progress) {
this.progress = progress;
postInvalidate(); // 在工作线程中更新视图
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制基于progress的视图
}
}
在上面的例子中,如果 setProgress
是在主线程中调用,也可以使用 invalidate()
。但使用 postInvalidate()
更为安全,因为它不受线程的限制。
总结
- 使用
invalidate()
当你确定你是在主线程中且需要更新UI。 - 使用
postInvalidate()
当你需要从非UI线程更新UI。
正确地使用这两个方法可以确保你的应用在多线程操作中仍能有效且安全地更新UI。