上文已经实现了圆环旋转,但是很多合格。发现之前对handler Thread Runnable理解的不深,包括如何刷新UI。这次总算清了一下帐,基本搞清除了。Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。参考这里,刷新UI有三种方式:
1.不使用多线程和双缓冲
这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 View的onDraw()方法。
2.使用多线程和不使用双缓冲
这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.
这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Message msg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量, 你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后再主线程中捕获、处理该消息。
3.使用多线程和双缓冲
Android中SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。
上面清晰也可以看到SurfaceView绘图和一般ImageView绘图的区别。一般采用第二种,个人觉的第二种里还是采用postInvalidate的方法好。因为invalidate是在主UI线程里,容易卡。尤其在退出程序的时候,这个很明显。所以刷新ImageView,让圆环转起来,我采用的是postInvalidate方法。
代码如下:
class UpdateThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 使用postInvalidate可以直接在线程中更新界面
postInvalidate();
}
}
}
注意这个postInvalidate(); 当执行这句话时,ImageView会自动调用onDraw()一次。在protected void onDraw(Canvas canvas) { }里进行画图就Ok了。正基于此,postInvalidate()这句话放在Thread.sleep(100);后面也是可以的,感觉这样反而更容易理解!在DrawImageView的构造函数里调用new Thread(new UpdateThread()).start()开启这个刷新线程。
另外,还有一点这种方式是定义一个UpdateThread,还可以直接在申请类的时候就实现这个接口如public class DrawImageView extends ImageView implements Runnable{},这样做的好处就是变量的申明和定义上。
举个例子,像http://blog.csdn.net/hui_ttoo/article/details/5390387这里提供的第二段示例程序:
class CustomizeView extends TextView {
public CustomizeView(Context context) {
super(context);
new Thread(new UIUpdateThread()).start();
}
class UIUpdateThread implements Runnable {
final Handler mHandler = new Handler();
final Runnable mUpdateResults = new Runnable() {
public void run() {
concreteUpdateUI();
invalidate();
}
};
public void run() {
// delay some minutes you desire.
/*try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
mHandler.post(mUpdateResults);
}
}
protected void concreteUpdateUI() {
// Add concrete movement for UI updates.
// ...
}
}
里面没有重载onDraw()函数,而是自己新建一个刷新Ui的函数,这个函数可以获取TextView然后更新时间阿。如果既有自己定义的updateUi又重载了onDraw()函数。由于updateUI是类UIUpdateThread 里面的子函数,如果不作处理,是无否调用全局的View成员。
但我不推荐上面这种写法,上面这种写法在线程中止时很可能会有问题。如果是用invalidate方法更新UI,我推荐这种写法:
// 在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();
}
}
}
}
参考:
http://www.cnblogs.com/tt_mc/archive/2012/01/30/2332023.html
http://www.blogjava.net/gooogle/archive/2008/03/05/184030.html
http://pwp5566.iteye.com/blog/1473159
http://kalogen.iteye.com/blog/1566111
http://blog.csdn.net/hui_ttoo/article/details/5390387 (前两个比较好)
分享到:
相关推荐
`Invalidate`和`postInvalidate`是Android提供的两种主要的View刷新机制,它们虽然都能达到更新界面的效果,但在使用场景和执行机制上有所区别。 首先,`Invalidate`方法是直接在UI线程中调用的。当调用一个View的`...
总结起来,理解Android中View的绘制流程和`invalidate()`的工作原理对于开发高质量的用户界面至关重要。通过合理利用这些知识,我们可以创建出更加灵活且高效的Android应用。在本Demo中,通过实现画多个圆圈的功能,...
总结来说,这个“Android自定义view之画圆环”的示例涵盖了许多Android开发中的核心概念,包括自定义View的创建、图形绘制、动画应用以及性能优化。通过学习和实践这个示例,开发者可以更好地理解和掌握Android图形...
- **Choreographer**:Android系统的动画和绘制调度器,负责协调View的绘制与动画帧,确保流畅的用户体验。 - **硬件加速**:从Android 3.0(Honeycomb)开始,系统默认开启了硬件加速,它利用GPU进行图形渲染,...
总之,Android自定义View的几何图形绘制涉及了对View类、Canvas API、Paint类的深入理解和应用,以及对图形布局和数据动态更新的理解。通过这些知识点,开发者能够创建出独具特色的图形界面,满足各种复杂的交互需求...
这个压缩包文件"Android高级应用源码-ImageViewEx 支持Gif显示的ImageView"提供了对GIF动图支持的`ImageView`扩展,名为`ImageViewEx`,它是一个增强版的图片视图,能够帮助开发者在Android应用中无缝地展示GIF动画...
综上所述,"Android圆盘旋转指针"是一个结合了自定义视图和动画技术的UI组件,它为Android应用带来了生动的视觉反馈。通过理解并实践这些知识点,开发者可以创建更多具有吸引力的UI元素,提升应用的整体质量。在`...
在Android开发中,View是构建用户界面的基本元素,它的绘制流程和`invalidate()`等相关方法是开发者需要深入理解的关键概念。本文将详细解析Android中View的绘制流程,以及`invalidate()`等核心方法的工作原理。 ...
在Android开发中,更新视图(View)是常见的任务,主要通过`invalidate()`和`postInvalidate()`这两个方法来实现。这两个方法都是用来触发View的重绘,但它们的使用场景和机制有所不同。 首先,`invalidate()`方法...
在Android开发中,自定义View是一种常见的需求,它允许开发者根据特定的需求来定制视图,以实现独特的交互和视觉效果。本示例“Android-自定义View绘制一个太极旋转图片demo”聚焦于如何通过自定义View来绘制并动画...
Android Studio是Google提供的集成开发环境(IDE),专门用于Android应用开发。它包含了编写、调试、构建以及测试Android应用所需的所有工具。在Android Studio中,我们可以利用Java或Kotlin这两种主要的编程语言来...
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 Android程序中可以使用的界面...
在Android开发中,自定义View是一项重要的技能,它允许开发者根据特定需求创建独特且功能丰富的用户界面。本项目“android自定义View-手绘地图”着重于如何利用自定义View来绘制地图,提供了两种实现方式:自定义...
在Android开发中,自定义控件是提升应用用户体验和实现独特功能的重要手段。本文将深入探讨如何基于Android的ImageView组件创建一个自定义视图,实现手势操作,包括图像的放大、缩小和旋转功能。 首先,我们需要...
总结起来,实现光点模糊渐变的自旋转圆环特效和水滴波纹特效,需要对Android自定义View、动画系统、图形绘制有深入的理解。通过熟练掌握这些技术,开发者可以创造出更多富有创意和吸引力的UI效果,提升应用的整体...
总的来说,自定义View在Android开发中具有广泛的应用,通过掌握`onMeasure()`和`onDraw()`方法,我们可以创建出各种复杂的UI组件,如这个案例中的可刷新验证码显示。在实践过程中,不断优化代码和提高用户体验,是...
在Android开发中,自定义画布Canvas是实现图形绘制的核心工具。Canvas提供了丰富的API,允许开发者在屏幕上绘制各种形状、图像以及文字等。本教程将深入探讨如何利用Canvas实现绘制和清空画布的功能。 首先,我们...
在Android开发中,自定义View是一项重要的技能,它允许开发者根据特定需求创建独特且功能丰富的UI组件。本项目"Android 自定义View实现水平温度计"就是这样一个实例,它通过自定义View来展示一个水平方向的温度计,...