`

利用Handler来更新android的UI

阅读更多

刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题

 new Thread( new Runnable() {   
    public void run() {   
         myView.invalidate();  
     }          
}).start();   

 

然而发现这样是不行的,因为它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。查阅了文档和apidemo后,发觉常用的方法是利用Handler来实现UI线程的更新的。

 

下面代码的功能很简单:画一个圆出来,每隔0.1秒,圆向10移动10个像素。但可以清楚展示利用Handler更新UI的流程。

 

 

首先创建简单的View,代码如下:

package com.ray.handler;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.view.View;

public class BounceView extends View {
    float x = 40;
    
    public BounceView(Context context) { 
         super(context); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
    	x+=10;
    	Paint mPaint = new Paint();
    	mPaint.setAntiAlias(true);
    	mPaint.setColor(Color.GREEN);
    	canvas.drawCircle(x, 40, 40, mPaint);
    }
}

 

创建Activity,代码如下:

package com.ray.handler;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.Window;

public class TestHandler extends Activity {
     protected static final int GUIUPDATEIDENTIFIER = 0x101; 
	 
     Thread myRefreshThread = null; 
     BounceView myBounceView = null; 
 
     Handler myHandler = new Handler() {
          public void handleMessage(Message msg) { 
               switch (msg.what) { 
                    case TestHandler.GUIUPDATEIDENTIFIER: 
                         myBounceView.invalidate();
                         break; 
               } 
               super.handleMessage(msg); 
          } 
     };
     public void onCreate(Bundle savedInstanceState) { 
          super.onCreate(savedInstanceState); 
          this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
 
          this.myBounceView = new BounceView(this);
          this.setContentView(this.myBounceView); 
          new Thread(new myThread()).start();
     } 
 
     class myThread implements Runnable { 
          public void run() {
               while (!Thread.currentThread().isInterrupted()) {  
                     
                    Message message = new Message(); 
                    message.what = TestHandler.GUIUPDATEIDENTIFIER; 
                    
                    TestHandler.this.myHandler.sendMessage(message); 
                    try { 
                         Thread.sleep(100);  
                    } catch (InterruptedException e) { 
                         Thread.currentThread().interrupt(); 
                    } 
               } 
          } 
     } 
}
42
2
分享到:
评论
14 楼 hxlniada 2014-07-22  
[color=darkred][/color][size=small][/size][align=right][/align]非常好的代码
13 楼 东方vs不败 2013-09-09  
写的不错,挺好的

12 楼 IWSo 2013-04-02  
leon_ch 写道
楼主既然用到BounceView来继承View,为什么不考虑用子空间的方式来实现呢?
另外,如果用handler来实现的话,那么利用activity内的内部类就可以循环实现,我自己做了一下,楼主看一下是不是可以?
第一种:
package edu.cslg.leon.ballinvalidate;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;

public class BallView extends View
{
private Paint paint;
private int BallX=10;
private int BallY=10;
private int WindowWidth=200;
private int WindowHeight=200;
static final int radius=20;

public BallView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint=new Paint();
}

@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
BallX++;
BallY++;
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(BallX, BallY, radius, paint);
if(BallX<WindowWidth&&BallY<WindowHeight)
{
invalidate();
}
}
}

配置文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <edu.cslg.leon.ballinvalidate.BallView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

第二种:
package edu.cslg.leon.ballinvalidate;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public class BallInvalidate extends Activity
{
private int BallX;
private int BallY;
private Paint paint;
private Canvas canvas;
static final int radius=20;
class MyHandler extends Handler
{
public MyHandler(Looper looper)
{
super(looper);
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(msg.arg1,msg.arg2, radius, paint);
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
paint=new Paint();
canvas=new Canvas();
new MyThread().start();
}
class MyThread extends Thread
{
@Override
public void run()
{
super.run();
while (BallX<200&&BallY<200)
{
Looper looper=Looper.getMainLooper();
Handler handler=new MyHandler(looper);
Message msg=handler.obtainMessage(1, BallX,BallY);
handler.sendMessage(msg);
}
}
}
}



你这个也对,实现的效果是一样的。
但楼主的重点不是要展现这个效果,而在于handler的使用
11 楼 KwokWing 2012-07-19  
最近学习Android游戏开发, 感谢楼主
10 楼 yacobe 2012-04-24  
条理很清晰,很受用。感谢
9 楼 yacobe 2012-04-24  
条理很清楚,很受用。感谢
8 楼 leon_ch 2012-04-12  
楼主既然用到BounceView来继承View,为什么不考虑用子空间的方式来实现呢?
另外,如果用handler来实现的话,那么利用activity内的内部类就可以循环实现,我自己做了一下,楼主看一下是不是可以?
第一种:
package edu.cslg.leon.ballinvalidate;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;

public class BallView extends View
{
private Paint paint;
private int BallX=10;
private int BallY=10;
private int WindowWidth=200;
private int WindowHeight=200;
static final int radius=20;

public BallView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint=new Paint();
}

@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
BallX++;
BallY++;
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(BallX, BallY, radius, paint);
if(BallX<WindowWidth&&BallY<WindowHeight)
{
invalidate();
}
}
}

配置文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <edu.cslg.leon.ballinvalidate.BallView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

第二种:
package edu.cslg.leon.ballinvalidate;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public class BallInvalidate extends Activity
{
private int BallX;
private int BallY;
private Paint paint;
private Canvas canvas;
static final int radius=20;
class MyHandler extends Handler
{
public MyHandler(Looper looper)
{
super(looper);
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(msg.arg1,msg.arg2, radius, paint);
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
paint=new Paint();
canvas=new Canvas();
new MyThread().start();
}
class MyThread extends Thread
{
@Override
public void run()
{
super.run();
while (BallX<200&&BallY<200)
{
Looper looper=Looper.getMainLooper();
Handler handler=new MyHandler(looper);
Message msg=handler.obtainMessage(1, BallX,BallY);
handler.sendMessage(msg);
}
}
}
}
7 楼 kevin2562 2010-03-09  
class myThread implements Runnable {   
          public void run() {  
               while (!Thread.currentThread().isInterrupted()) {    
                       
                    Message message = new Message();   
                    message.what = TestHandler.GUIUPDATEIDENTIFIER;   
                      
                    TestHandler.this.myHandler.sendMessage(message);   
                    try {   
                         Thread.sleep(100);    
                    } catch (InterruptedException e) {   
                         Thread.currentThread().interrupt();   
                    }   
               }   
          }   


这段有点不理解,楼主能解释一下么?
尤其是:
   while (!Thread.currentThread().isInterrupted()) { 

   message.what = TestHandler.GUIUPDATEIDENTIFIER;
   
   TestHandler.this.myHandler.sendMessage(message);

  Thread.currentThread().interrupt();

作用是什么?

我很喜欢楼主的学习风格,在此表示感谢,你的帖子对我很有帮助。
6 楼 happyljt 2010-01-25  
学习ing...
5 楼 crazier9527 2009-12-30  
TestHandler.this.myHandler
4 楼 raymondlueng 2009-10-15  
chenweiguo66 写道
不用Handler行吗?在你的另一篇文章中http://www.iteye.com/topic/435147,
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
用handler可以更好地使用消息
驱动的程序设计!类似mfc[color=red][/color]
3 楼 chenweiguo66 2009-10-15  
不用Handler行吗?在你的另一篇文章中http://www.iteye.com/topic/435147,
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
2 楼 raymondlueng 2009-09-11  
呵呵,其实我只是初学者,只能写简单的东西!
1 楼 neverland 2009-09-11  
兄弟写的文章很清晰,~~感谢

相关推荐

    Android Handler定时更新UI

    在Android应用开发中,Handler是实现线程间通信的关键组件,尤其在涉及到UI更新时,它的作用尤为重要。本文将深入探讨“Android Handler定时更新UI”的相关知识点,以及如何使用CounterDemo来实现这一功能。 首先,...

    使用Handler实现异步更新UI例子

    在分析了Handler的工作原理和使用方法后,我们可以看到,异步更新UI的核心是利用了Android的消息传递机制,让主线程与工作线程之间能有效地协同工作。通过Handler,我们可以在不影响UI性能的情况下执行后台任务,...

    利用Handler实时更新时间

    在Android开发中,实时更新界面元素常常涉及到线程间的通信,这里主要讲解如何利用Handler、Timer、TimerTask和Message这四个关键组件来实现这一功能。首先,我们需要理解这些组件的基本概念和作用。 **Handler** ...

    Android广播onReceiver回调更新ui

    通常,我们推荐使用Handler或AsyncTask来异步处理UI更新。在主线程(UI线程)中更新UI,确保操作的顺利进行。 5. **测试广播接收器**: 文件名为"testbroadcast"可能是一个用于测试广播接收器的类或项目。测试广播...

    Android利用handler在线程之间传递代码

    在Android应用开发中,线程间的通信是一个至关重要的概念,特别是在UI更新和后台任务执行时。Handler机制就是Android系统提供的一种高效、灵活的线程间通信方式。本篇将深入探讨如何利用Handler在线程之间传递代码,...

    通过Messenger实现Android Service更新UI

    这时,我们可以利用Android的Binder机制中的Messenger来实现这种跨进程通信(IPC,Inter-Process Communication)。本篇将详细介绍如何通过Messenger实现在Service中更新UI。 首先,理解Messenger的核心概念。...

    更新UI android

    当子线程完成部分工作或需要更新UI时,会通过特定方式(如Handler的post方法或runOnUiThread)将消息传递回主线程进行UI更新,确保界面的流畅性。 4. **更新UI的策略**: - **Handler-Looper机制**:主线程中有一...

    利用Handler+ArrayList来处理并发事件

    在Android开发中,多线程和并发处理是常见的需求,特别是在UI更新和后台任务执行时。本主题将深入探讨如何利用Handler和ArrayList来处理并发事件,以实现高效且线程安全的操作。 首先,理解Handler机制至关重要。...

    理解handler,message,Android简单时钟程序

    在Android开发中,`Handler`、`Message`和线程管理是至关重要的概念,尤其是在创建实时更新的应用,如时钟程序时。让我们深入探讨这些概念...通过实践这样的程序,开发者可以更深入地理解Android的多线程和UI更新机制。

    android demo,使用Handler的postDelay,Runnable run实现延时3秒的splash。

    本示例中的“android demo”就是关于如何利用Handler的`postDelayed`方法和`Runnable`接口来实现一个延时3秒的Splash Screen。下面将详细解释这个过程以及涉及的技术点。 1. **Handler**: Handler是Android中处理...

    Android-UI-TimerTask.rar_android_android timetask_android ui

    可以使用`runOnUiThread()`或者`Handler`来确保在主线程执行UI更新操作。 ```java runOnUiThread(new Runnable() { @Override public void run() { // 更新UI的操作 } }); ``` 5. **注意事项**: - 为了...

    详解Android UI更新的几种方法

    Android UI更新方法详解 Android UI更新是 Android 应用程序开发中一个非常重要的步骤。在 Android 开发中,界面 UI 的更新都是在主线程来完成的。线程分为主线程(Main Thread,简称 MT)和工作线程(WorkThread...

    Android 线程更新UI

    1. **主线程(UI线程)**:应用程序启动时默认创建的线程,负责处理所有的用户交互和UI更新。由于Android系统规定,所有的UI操作都必须在主线程进行,以保证界面的流畅性。 2. **工作线程(Worker Thread)**:用于...

    Android Handler Looper

    在Android应用开发中,Handler、Looper和Message是实现线程间通信的重要机制,尤其是在主线程与工作线程之间同步数据和执行UI更新时。Handler、Looper和Message三者结合使用,构建了一个消息处理系统,使得非UI线程...

    Android_Handler的线程队列Demo

    这个"Android_Handler的线程队列Demo"旨在演示如何有效地利用Handler来处理线程间的通信,特别是主线程(UI线程)与工作线程之间的交互。下面我们将深入探讨相关知识点。 首先,了解Handler的基本概念。Handler是...

    android计数器(Handler消息传递机制)

    通过这个简单的计数器应用,我们可以理解`Handler`如何协同`Looper`和`MessageQueue`工作,以及如何在Android中实现定时任务,特别是涉及到UI更新的操作。这种机制在更复杂的异步编程和事件驱动设计中也扮演着关键...

    [毕设季 android开发]第六讲:Android线程及UI更新

    本讲将深入探讨Android线程的使用,特别是如何利用Handler来实现在主线程中更新UI。Handler是Android中的一个消息处理机制,它与Looper和Message紧密配合,用于在不同的线程间传递消息并执行相应的回调方法。 1. **...

Global site tag (gtag.js) - Google Analytics