在Android中,使用Handler来控制UI程序界面的变化,Handler的作用为与其他线程协同工作,接收其他线程的消息,并通过接收到的消息更新主UI线程的内容。
在Android中我们将一些耗时的操作放到子线程中执行,但因为子线程涉及到ui更新,而android的主线程是线程不安全的,所以更新UI的操作只能放在子线程中去执行,所以引入一种机制,就是UI线程用来发送名命令/任务给子线程,然后子线程返回执行的结果。
工作原理:
一般情况下,在主线程中绑定Handler,并在事件触发上面创建新线程用于完成某些耗时的操作,当在线程中的工作完成后,会对handler发送一个完成的信号, 而Handler接收到信号后。就进行UI界面的更新操作。
必知知识:
若在主线程中实例化一个handler对象,Handler handler = new Handler(),此时并没有派生出一个线程来执行handler,而是将此handler附加在主线程上,因此在handler中不能进行耗时的操作。
在Handler必然要使用Message
Message 为消息对象,就是记录消息信息的类 ,有如下几个重要的字段,
1:arg1 , arg2 :可以用这两个字段来存放需要传递的整型值,在Service中,用来存放ServiceID。
2:obj:该字段是Object类型, 可以让该对象传递某个多项消息,
3:what:消息的标志,可以根据这个字段的不同的值进行不同的处理。
在使用Message时,可以通过newMessage()获取message的实例,但是Android更推荐我们通过Message.obtain()或者Handler.obtainMessage()获取Message的对象,推荐使用的方法并不是直接创建一个实例,而是从消息池中看有没有可用的Message实例,存在则直接使用,不存在则创建一个新的对象Android系统默认情况下,在消息池中实例化10个Message对象。
下面通过一个完成网络图片下载的实例说明handler的用法:
public class MainActivity extends Activity {
private Button button = null;;
private ImageView img = null;
private String img_url = "http://pic19.nipic.com/20120323/9248108_140027253135_2.jpg";
private final int IS_FINISH = 0x1234;
private ProgressDialog dialog = null;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
byte[] data = (byte[]) msg.obj; //将图片的信息存放在字节数组中
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);//将字节转换为位图
img.setImageBitmap(bm);//更新位图
if (msg.what == IS_FINISH) {
dialog.dismiss();
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.imageView);
button = (Button) findViewById(R.id.button);
dialog = new ProgressDialog(this);
dialog.setTitle("提示");
dialog.setMessage("正在下载,请稍后。。。。。。");
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new MyThread()).start();
dialog.show();
}
});
}
public class MyThread implements Runnable {
@Override
public void run() {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(img_url);
try {
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
byte[] data = EntityUtils.toByteArray(response.getEntity());//将请求到的信息放在字节数组中。
// 发送消息给主线程
Message message = Message.obtain(); //创建一个对象
message.obj = data;// obj存放下载图片的信息
message.what = IS_FINISH;
handler.sendMessage(message);// 发送消息
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}