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