Handler的使用(一)

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:执行结果如下

原文地址:https://www.cnblogs.com/chenbin7/p/2497173.html