java代码
-
package com.example.handlertest;
-
-
import android.os.Bundle;
-
import android.os.Handler;
-
import android.os.Looper;
-
import android.os.Message;
-
import android.app.Activity;
-
import android.view.Menu;
-
import android.view.View;
-
import android.view.View.OnClickListener;
-
import android.widget.Button;
-
/**
-
* 通过一个demo来讲解下几种Handler处理的情况
-
*
-
*
-
*
-
* 为了引入Handler消息机制,我们必须先知道“同步”和“异步”通信的差别
-
*
-
* “同步”通信: 比如 我打电话给小明,跟小明进行对话,我必须等到和小明结束通话之后,才能再拨打其他人的电话
-
* (同步就是发送一个请求之后,什么事都不做,一直等到结果返回后才继续做下面的事情)
-
*
-
* "异步"通信: 比如 我给几个同学发送E-mail邮件,全部发送过去之后,不需要在这边等他们回复,
-
我还可以去做别的事情,他们回复的时候,邮箱系统会通知我
-
* (异步就是发出请求之后,这个请求完成之后,通过状态,通知或者回调等方式来通知调用者处理的结果)
-
*
-
*
-
* Handler机制的产生原因: 一个应用程序开启之后,首先会开启一个UI线程(主线程),顾名思义是用来管理界面中UI控件的,
-
* 并对事件进行分发,比如一个Button的点击事件,android把事件分发到对应的Button上,来响应用户操作
-
* 但由于用户有可能需要做一些耗时的操作(下载文件),但是android如果5秒钟界面没反应的话,就会提示
-
* 用户关闭应用程序了,所以这时候需要把这些耗时的操作放在 子线程 中处理,子线程处理完成之后再去更新
-
* UI线程中的界面,而Android的UI线程又是不安全的,这样意味着子线程中无法直接更新UI线程的界面,
-
* 因此Android中设计了Handler来解决这个问题!
-
*
-
* 解决方法: Handler运行在UI线程中,它与子线程可通过Message对象来传递数据,这时候,handler就承担了接收子线程
-
* 传来的Message对象的责任,从而配合UI线程更新UI。
-
*
-
*
-
* Handler消息机制:
-
*
-
*
-
* 1.handler存取消息的原理:
-
*
-
* Handler允许发送并处理Message消息,Message消息通过主线程的MessageQueue消息队列相关联的Message和
-
* Runnable对象进行存取,当创建一个新的handler时(在主线程中创建),handler就属于当前主线程,主线程的
-
* MessageQueue也同步创建,Handler会绑定到该主线程/消息队列中,这样,handler就可以通过主线程的消息队列
-
* 发送和接收Message消息对象了
-
*
-
*
-
* 2.Handler消息处理机制的几种情况[下面用代码来说明这几种情况]: 2.1 button1: 主线程中做Handler 2.2
-
button2:
-
* 子线程中做Handler 2.3 button3: 把主线程创建的Handler传递给其他线程完成消息处理 2.4 button4:
-
* 在其他线程中更新UI线程界面,它抛出异常,我们看看哈~!
-
*
-
*
-
*
-
*
-
发送Message不会阻塞线程(异步),而接收消息处理会阻塞线程[当Handler处理完一个Message对象后才会接着去取下一个消息进行处理](同步)
-
*
-
*
-
* 2013年09月11日23:37:08
-
*
-
* @author xiaoyaomeng
-
*
-
*/
-
public class MainActivity extends Activity implements OnClickListener {
-
HandlerDemo myHandlerDemo = null;// 该对象用于主线程中创建handler
-
Button button1 = null;
-
Button button2 = null;
-
Button button3 = null;
-
Button button4 = null;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
button1 = (Button) findViewById(R.id.button1);
-
button2 = (Button) findViewById(R.id.button2);
-
button3 = (Button) findViewById(R.id.button3);
-
button4 = (Button) findViewById(R.id.button4);
-
button1.setOnClickListener(this);
-
button2.setOnClickListener(this);
-
button3.setOnClickListener(this);
-
button4.setOnClickListener(this);
-
}
-
@Override
-
public boolean onCreateOptionsMenu(Menu menu) {
-
// Inflate the menu; this adds items to the action bar if it is
-
present.
-
getMenuInflater().inflate(R.menu.main, menu);
-
return true;
-
}
-
@Override
-
public void onClick(View v) {
-
// TODO Auto-generated method stub
-
handlerDealMessage(v.getId());
-
}
-
private void handlerDealMessage(int id) {
-
// TODO Auto-generated method stub
-
switch (id) {
-
case R.id.button1: {
-
// 主线程中创建Handler实例
-
myHandlerDemo = new HandlerDemo();
-
Message message = myHandlerDemo.obtainMessage(1,
-
(Object) ("Hello,My name is Handler1~~"));
-
message.sendToTarget();// Handler发送消息,会对应发送到这个和这个Handler绑定的UI线程做处理
-
}
-
break;
-
case R.id.button2: {
-
MyThread myThread = new MyThread();
-
myThread.start();
-
}
-
break;
-
case R.id.button3: {
-
myHandlerDemo = new HandlerDemo();
-
OtherThread otherThread = new OtherThread(myHandlerDemo);
-
otherThread.start();
-
}
-
break;
-
case R.id.button4: {
-
errorHandlerThread errorHandlerThread = new errorHandlerThread(
-
button4);
-
errorHandlerThread.start();
-
}
-
break;
-
default:
-
break;
-
}
-
}
-
/*
-
* MyThread 是内部类,子线程
-
*/
-
private class MyThread extends Thread {
-
@Override
-
public void run() {
-
// TODO Auto-generated method stub
-
super.run();
-
// 1.error: 只能在UI线程中采用不带Looper对象创建Handler对象,所以此处会报异常
-
// myHandlerDemo = new HandlerDemo();
-
// 2.error: Looper.myLooper获取的Looper是null,所以也会报异常
-
// myHandlerDemo = new HandlerDemo(Looper.myLooper());
-
//
-
通过Looper.getMainLooper()可以得到父类的looper,所以可以成功创建handler对象并绑定MessageQueue
-
myHandlerDemo = new HandlerDemo(Looper.getMainLooper());
-
Message message = myHandlerDemo.obtainMessage(2,
-
(Object) ("Hello,My name is Handler2~~"));
-
message.sendToTarget();
-
}
-
}
-
private/**
-
* 创建一个Handler
-
*
-
* @author xiaoyaomeng
-
*
-
*/
-
class HandlerDemo extends Handler {
-
/* 在UI线程中创建handler时,可以直接调用这个构造函数 */
-
public HandlerDemo() {
-
super();
-
// TODO Auto-generated constructor stub
-
}
-
/* 在子线程中创建一个Handler需要用到这个构造函数,否则报错 */
-
public HandlerDemo(Looper looper) {
-
super(looper);
-
// TODO Auto-generated constructor stub
-
}
-
@Override
-
public void handleMessage(Message msg) {
-
// TODO Auto-generated method stub
-
super.handleMessage(msg);
-
switch (msg.what) {
-
case 1: {
-
button1.setText(msg.obj.toString());
-
}
-
break;
-
case 2: {
-
button2.setText(msg.obj.toString());
-
}
-
break;
-
case 3: {
-
button3.setText(msg.obj.toString());
-
}
-
break;
-
default:
-
break;
-
}
-
}
-
}
-
}
-
/**
-
*
-
* 其他线程的类,用来接收一个handler,并在线程中 用这个handler发送消息
-
*
-
* @author xiaoyaomeng
-
*
-
*/
-
class OtherThread extends Thread {
-
private Handler mHandler;
-
public OtherThread(Handler handler) {
-
// TODO Auto-generated constructor stub
-
mHandler = handler;
-
}
-
@Override
-
public void run() {
-
// TODO Auto-generated method stub
-
super.run();
-
Message message = mHandler.obtainMessage(3,
-
(Object) ("Hello,My name is Handler3~~"));
-
message.sendToTarget();
-
}
-
}
-
/**
-
* 测试错误报错的线程
-
*
-
* @author xiaoyaomeng
-
*
-
*/
-
class errorHandlerThread extends Thread {
-
Button button = null;
-
public errorHandlerThread(Button button) {
-
// TODO Auto-generated constructor stub
-
this.button = button;
-
}
-
@Override
-
public void run() {
-
// TODO Auto-generated method stub
-
super.run();
-
button.setText("hahahaha~~~");
-
}
- }