android
Handler.post(action) 这是android提供的一种机制,handler对象将通过post方法,将里面的Runnable对象放到UI执行队列中,UI消费这个队列,调用Runnable的run方法。这里并不生成新的线程。
Android中在绘图中的多线程中,invalidate和postInvalidate这两个方法是用来刷新界面的,调用这两个方法后,会调用onDraw事件,让界面重绘。
在一个没有使用线程的小游戏中想刷新一下时间进度,想到用Timer。于是写了一段代码:
nStartRoundTime = System.currentTimeMillis();
nT1 = new Timer();
nT1.schedule(new TimerTask(){ //计划运行时间间隔
public void run(){
refreshTimePaint(); //过3秒调用一下refreshTimePaint()
}
},0,3000);
public void refreshTimePaint(){
invalidate(); //使用invalidate();刷新
System.out.println(System.currentTimeMillis());
System.out.println(nGameState);
}
同时我也将System.currentTimeMillis()打印在View上。
运行一下,发现并不是预期那样, System.out.println的结果在Log里面都有变化,但是View却没有反应。 不但View上面没有被刷新,甚至连原来的触屏事件都没有反映了。
去网上查了一下,得到的一些解释有这些:
The best thing is to use Handler with delayed messages.
And Timer works fine, the problem is that a Timer runs in a separate thread, and so you are trying to modify a view owned by another thread (the main thread that originally created it).
What I think is happening is you're falling off the UI thread. There is a single "looper" thread which handles all screen updates. If you attempt to call "invalidate()" and you're not on this thread nothing will happen.
Try using "postInvalidate()" on your view instead. It'll let you update a view when you're not in the current UI thread.
于是把refreshTimePaint()的代码改成:
public void refreshTimePaint(){
this.postInvalidate(); //使用postInvalidate();刷新
System.out.println(System.currentTimeMillis());
System.out.println(nGameState);
}
这样View就能自动刷新了~~~
这里有几个网页做参考:
http://stackoverflow.com/questions/522800/android-textview-timer
http://groups.google.com/group/android-developers/browse_thread/thread/5baf5a3eaa823b7b?pli=1
http://groups.google.com/group/android-developers/msg/f5765705b8c59d66
分享到:
相关推荐
Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。 Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在...
在Android开发中,更新View是常见的任务,而`invalidate()`和`postInvalidate()`就是用于这一目的的关键方法。这两者都是用来标记一个View为脏(dirty),需要重新绘制,但它们在使用场景和机制上有所不同。 1. `...
`postInvalidate()`在UI线程之外调用,用于异步地请求重绘,适用于非UI线程修改了View的状态。`invalidateRect()`允许指定一个矩形区域进行重绘,这样可以只更新变化的部分,提高性能。`invalidateParent()`会通知父...
开发者可以通过创建`Handler`实例、定义`Runnable`并使用`post()`或`postDelayed()`来安排UI更新,或者直接在子线程中调用`postInvalidate()`来触发视图的重绘。在实际项目中,这种异步更新UI的方法非常常见,也是...
【Android invalidate()与postInvalidate()用法】 invalidate()方法用于立即重新绘制View,而postInvalidate()则会在UI线程的下一个事件循环中触发重绘。如果需要在非UI线程中更新视图,应使用postInvalidate()。 ...
handler.post(drawRunnable); ``` `updateSnowflakes()`方法应检查雪花是否超出屏幕边界,并在必要时将其移动到屏幕顶部重新开始下落。同时,可以随机调整雪花的下落速度、旋转速度以及是否改变大小,以增加真实感...
post(scrollRunnable); } // 停止滚动 stopScroll() { removeCallbacks(scrollRunnable); } ``` 此外,为了实现数据结构和传递数据给View,我们可以将文本数据存储在一个列表中,然后根据需要动态更新。例如,...
invalidate()会立即重新绘制View,而postInvalidate()会在UI线程的下一个事件循环中执行,这在跨线程更新UI时特别有用。 11. **Android消息机制**: 安卓的消息机制基于Looper、Handler和Message,用于在不同线程...
UI刷新方面,Invalidate()方法用于主线程刷新UI,而postInvalidate()用于非主线程刷新,常在线程中使用。注意,不要在主线程中进行阻塞操作,比如长时间循环,以免导致应用无响应。抗锯齿效果可以通过设置Paint的...
可能的优化策略包括使用硬件加速、减少不必要的绘制调用、合理使用invalidate()和postInvalidate(),以及适时地暂停和恢复动画。 6. **触摸事件处理**:为了增加交互性,MoveBackgroundSample可能还涉及触摸事件的...
- 使用` invalidate()`或`postInvalidate()`通知系统重绘UI,确保秒表数值的实时更新。 8. **线程管理**: - 因为Android应用的主线程(UI线程)不允许执行耗时操作,所以计时器的更新和回调通常发生在后台线程中...
- 在`run()`方法中,需要不断更新UI,这通常通过`View.postInvalidate()`或`View.invalidate()`方法来实现,它们会触发界面的重绘。 2. **使用Handler和Runnable** - 创建一个Handler对象,通常在主线程(UI线程...
我们可以使用Handler或Runnable配合postInvalidate()方法来定期重绘视图,以实现图形的动态变化。例如,让矩形持续改变位置: ```java private float rectX = 10; private float rectY = 10; // 在构造函数或...
当View的状态发生改变,需要重新绘制时,会触发View的invalidate()或postInvalidate()方法,这些方法会将View添加到待绘制队列中,然后由Android系统的 Choreographer 组件调度在合适的时机执行draw()方法进行重绘...
为了让时钟实时更新,我们需要在`MyClock`类中添加一个`Runnable`,并在`postInvalidate()`方法中定时调用它,以便每秒刷新一次时钟。 ```java private final Runnable updateTask = new Runnable() { @Override ...
例如,减少不必要的绘制操作,使用`View.postInvalidate()`来局部刷新界面,避免全局` Invalidate()`导致的全屏重绘。另外,如果游戏包含大量图形,可能需要使用硬件加速,通过在XML布局文件中设置`android:hardware...