当前位置: 代码迷 >> Android >> 利用Handler回更新android的UI
  详细解决方案

利用Handler回更新android的UI

热度:94   发布时间:2016-05-01 14:09:40.0
利用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();                     }                }           }      } }
1 楼 neverland 2009-09-11  
兄弟写的文章很清晰,~~感谢
2 楼 raymondlueng 2009-09-11  
呵呵,其实我只是初学者,只能写简单的东西!
3 楼 chenweiguo66 2009-10-15  
不用Handler行吗?在你的另一篇文章中http://www.iteye.com/topic/435147,
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
4 楼 raymondlueng 2009-10-15  
chenweiguo66 写道
不用Handler行吗?在你的另一篇文章中http://www.iteye.com/topic/435147,
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
用handler可以更好地使用消息
驱动的程序设计!类似mfc[color=red][/color]
5 楼 crazier9527 2009-12-30  
TestHandler.this.myHandler
6 楼 happyljt 2010-01-25  
学习ing...
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();

作用是什么?

我很喜欢楼主的学习风格,在此表示感谢,你的帖子对我很有帮助。
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);
}
}
}
}
9 楼 yacobe 2012-04-24  
条理很清楚,很受用。感谢
10 楼 yacobe 2012-04-24  
条理很清晰,很受用。感谢
11 楼 KwokWing 2012-07-19  
最近学习Android游戏开发, 感谢楼主
  相关解决方案