Handler的定义(感觉讲得挺好的):主要接受子线程发送的数据, 并用此数据配合主线程更新UI.
解释:
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程), 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个Button,Android会分发事件到Button上,来响应你的操作.如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭".这个时候我们需要把这些耗时的操作,放在一个子线程中。
更新UI只能在主线程中更新,子线程中操作是危险的。这个时候,Handler就出现了。Android提供了Handler作为主线程和子线程的纽带。同时,Handler对象初始化后,就默认与对它初始化的进程的消息队列(该消息队列由Looper控制)绑定。Handler可以把消息和Runnble对象发送到与Handler对象所关联的消息队列中去。
ps:不管是消息还是Runnable对象,都是发送到所在线程的消息队列中,不存在所谓的线程队列...不知道为什么别人总是说Handler绑定两个队列(消息队列,线程队列)?
1.传递Message:
如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,由Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。
首先handler通过obtainMessage获取消息对象,然后通过sendMessage方法发送消息对象到消息队列中,再调用handleMessage方法处理消息。 ps:(调用sendMessage方法送入消息队列后,会自动调用handleMessage方法)
2.传递Runnable对象:
1. 先创建一个handler对象
2. 创建一个Runnable对象,将要执行的动作写入线程的run中
3. 调用handler的post方法把将Runnable对象加入到消息队列中
方法作用:
(1)post方法的作用:将Runnable对象加入到消息队列中.
Google Android文档中的Post()方法:将Runnable对象r添加到消息队列中。这个Runnable对象运行在handler绑定的线程上。
原文:Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.
(2)removeCallbacks方法的作用:从消息队列中将Runnable对象删除
通过以下实例来演示操作,创建项目步骤:
step1:新建android工程,命名为HandlerTest。
step2:设置布局文件main.xml
<?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" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="开始"/> <Button android:id="@+id/button2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="结束"/> <ProgressBar android:id="@+id/bar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:visibility="gone"/> </LinearLayout>
step3:设计主类HandlerTest.java
1 package com.cb.handler; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Message; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.widget.Button; 10 import android.widget.ProgressBar; 11 12 public class HandlerTest extends Activity { 13 private ProgressBar mProgressBar; 14 private Button mStartButton; 15 private Button mEndButton; 16 17 @Override 18 public void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.main); 21 22 mProgressBar = (ProgressBar)findViewById(R.id.bar1); 23 mStartButton = (Button)findViewById(R.id.button1); 24 mEndButton = (Button)findViewById(R.id.button2); 25 26 //开始按钮触发事件 27 mStartButton.setOnClickListener(new OnClickListener() { 28 29 @Override 30 public void onClick(View v) { 31 mProgressBar.setVisibility(View.VISIBLE); 32 updateBarHandler.post(updateThread); 33 } 34 }); 35 36 //结束按钮触发事件 37 mEndButton.setOnClickListener(new OnClickListener() { 38 39 @Override 40 public void onClick(View v) { 41 updateBarHandler.removeCallbacks(updateThread); 42 mProgressBar.setVisibility(View.GONE); 43 } 44 }); 45 } 46 47 //使用匿名内部类来复写handleMessage方法 48 Handler updateBarHandler = new Handler(){ 49 50 @Override 51 //handleMessage方法的作用:从消息队列中取出消息对象 52 public void handleMessage(Message msg) { 53 mProgressBar.setProgress(msg.arg1); 54 //post方法的作用:将Runnable对象加入到消息队列中. 55 updateBarHandler.post(updateThread); 56 } 57 58 }; 59 60 //线程类,使用匿名内部类来声明 61 Runnable updateThread = new Runnable() { 62 int i = 0; 63 @Override 64 public void run() { 65 i = i + 10; 66 67 //得到一个消息对象,Message类是由android提供 68 Message msg = updateBarHandler.obtainMessage(); 69 70 //将msg对象的arg1参数设置为i,用arg1.arg2两个成员变量传递消息,优点是系统性能消耗较少 71 msg.arg1 = i; 72 73 try { 74 Thread.sleep(1000); 75 } catch (Exception e) { 76 e.printStackTrace(); 77 } 78 79 /*Pushes a message onto the end of the message queue after all pending messages before the current time. 80 * It will be received in handleMessage, in the thread attached to this handler. 81 * 说明调用sendMessage方法加入消息后,会调用handleMessage方法. 82 */ 83 84 //sendMessage方法的作用:将消息加入到消息队列中 85 updateBarHandler.sendMessage(msg); 86 87 if (i == 100) { 88 //removeCallbacks方法的作用:将Runnable对象从消息队列中移除 89 updateBarHandler.removeCallbacks(updateThread); 90 } 91 if (i > 100) { 92 //i的值大于100时,设置进度条不可见 93 mProgressBar.setVisibility(View.GONE); 94 95 //将i置0,那么重新点开始按钮时,进度条也重新开始执行 96 i = 0; 97 } 98 } 99 }; 100 }
step4:执行结果如下