Android中利用Handler在子线程中更新界面--简单的小球上下跳动案例

转自:http://blog.csdn.net/a13429921973/article/details/9279941
前言:

当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序还会挂掉。Handler就是把这些功能放到一个单独的线程里执行,与Activity互不影响。当用户点击一个按钮时如果执行的是一个常耗时操作的话,处理不好会导致系统假死,用户体验很差,而Android则更进一步,如果任意一个Acitivity没有响应5秒钟以上就会被强制关闭,因此我们需要另外起动一个线程来处理长耗时操作,而主线程则不受其影响,在耗时操作完结发送消息给主线程,主线程再做相应处理。那么线程之间的消息传递和异步处理用的就是Handler。
以下模拟一个简单的小球上下跳动的案例来分析Handler的工作模式。

源码:

MyView.java

  1. public class MyView extends View {  
  2.     // 图形当前坐标   
  3.     private int x = 20, y = 20;  
  4.     public int getX() {  
  5.         return x;  
  6.     }  
  7.   
  8.     public void setX(int x) {  
  9.         this.x = x;  
  10.     }  
  11.   
  12.     public int getY() {  
  13.         return y;  
  14.     }  
  15.   
  16.     public void setY(int y) {  
  17.         this.y = y;  
  18.     }  
  19.   
  20.     public MyView(Context context, AttributeSet attrs) {  
  21.         super(context, attrs);  
  22.         this.setFocusable(true);  
  23.     }  
  24.   
  25.     @Override  
  26.     protected void onDraw(Canvas canvas) {  
  27.         super.onDraw(canvas);  
  28.         // 实例化画笔   
  29.         Paint p = new Paint();  
  30.         // 设置画笔颜色   
  31.         p.setColor(Color.GREEN);  
  32.         // 画图   
  33.         canvas.drawCircle(x, y, 10, p);  
  34.     }  
  35.   
  36. }  
public class MyView extends View {
	// 图形当前坐标
	private int x = 20, y = 20;
	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.setFocusable(true);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 实例化画笔
		Paint p = new Paint();
		// 设置画笔颜色
		p.setColor(Color.GREEN);
		// 画图
		canvas.drawCircle(x, y, 10, p);
	}

}

MainActivityDraw.java

  1. public class MainActivityDraw extends Activity {  
  2.     private MyView myView;  
  3.     private MyHandler mHandler;  
  4.     private static final int UPDATE = 1;  
  5.   
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.         myView = (MyView) findViewById(R.id.myView);// myView是主线程里的UI,所以不能在子线程里更新   
  11.         mHandler = new MyHandler();// 在主线程中创建Handler ,该Handler与主线程进行了绑定   
  12.         // 匿名子线程对象   
  13.         new Thread() {  
  14.             public void run() {               
  15.                 //只要当前线程没有被打断,就一直循环   
  16.                 while (!Thread.currentThread().isInterrupted()) {  
  17.                     System.out.println("Thread------id------>"+Thread.currentThread().getId());//显示子线程id   
  18.                     System.out.println("Thread------name------>"+Thread.currentThread().getName());//显示子线程name   
  19.                     Message msg = mHandler.obtainMessage(UPDATE);//这一个要放在while循环里面   
  20.                     mHandler.sendMessage(msg);//发送一个消息给mHandler   
  21.                     try {  
  22.                         Thread.sleep(300);  
  23.                     } catch (InterruptedException e) {  
  24.                         e.printStackTrace();  
  25.                     }  
  26.                 }  
  27.             }  
  28.         }.start();  
  29.     }  
  30.     private class MyHandler extends Handler {  
  31.           
  32.         @Override  
  33.         public void handleMessage(Message msg) {  
  34.             System.out.println("handle--id-->"+Thread.currentThread().getId());//1   
  35.             System.out.println("handle--name-->"+Thread.currentThread().getName());//显示为main主线程   
  36.             super.handleMessage(msg);  
  37.             switch (msg.what) {  
  38.             case UPDATE:// 在收到消息时,对界面进行更新 ,Handler处于主线程,可以对UI进行更新   
  39.                 updatePoint();//更新myView里的画笔坐标   
  40.                 myView.invalidate();//更新myView   
  41.                 break;  
  42.             }  
  43.         }  
  44.     }  
  45.     // 更新坐标   
  46.     private void updatePoint() {  
  47.         int h = myView.getHeight();  
  48.         int y = myView.getY();  
  49.         y = y + 5;  
  50.         if (y >= h) {  
  51.             y = 20;  
  52.         }  
  53.         myView.setY(y);//很关键,要将更新过后的Y的值传过去   
  54.     }  
  55. }  
public class MainActivityDraw extends Activity {
	private MyView myView;
	private MyHandler mHandler;
	private static final int UPDATE = 1;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		myView = (MyView) findViewById(R.id.myView);// myView是主线程里的UI,所以不能在子线程里更新
		mHandler = new MyHandler();// 在主线程中创建Handler ,该Handler与主线程进行了绑定
		// 匿名子线程对象
		new Thread() {
			public void run() {				
				//只要当前线程没有被打断,就一直循环
				while (!Thread.currentThread().isInterrupted()) {
					System.out.println("Thread------id------>"+Thread.currentThread().getId());//显示子线程id
					System.out.println("Thread------name------>"+Thread.currentThread().getName());//显示子线程name
					Message msg = mHandler.obtainMessage(UPDATE);//这一个要放在while循环里面
					mHandler.sendMessage(msg);//发送一个消息给mHandler
					try {
						Thread.sleep(300);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}
	private class MyHandler extends Handler {
		
		@Override
		public void handleMessage(Message msg) {
			System.out.println("handle--id-->"+Thread.currentThread().getId());//1
			System.out.println("handle--name-->"+Thread.currentThread().getName());//显示为main主线程
			super.handleMessage(msg);
			switch (msg.what) {
			case UPDATE:// 在收到消息时,对界面进行更新 ,Handler处于主线程,可以对UI进行更新
				updatePoint();//更新myView里的画笔坐标
				myView.invalidate();//更新myView
				break;
			}
		}
	}
	// 更新坐标
	private void updatePoint() {
		int h = myView.getHeight();
		int y = myView.getY();
		y = y + 5;
		if (y >= h) {
			y = 20;
		}
		myView.setY(y);//很关键,要将更新过后的Y的值传过去
	}
}
验证结果:

运行界面:

           

案例源码:

csdn资源下载(免费):http://download.csdn.net/detail/a13429921973/5725107

特别提醒:

本博客部分参考:http://rd.189works.com/article-12493-1.html

详情请参考该网址




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值