秒钟还没有完成的话,会收到Android系统的一个错误提示  "强制关闭".  这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的.这个时候,Handler就出现了来解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)  ,把这些消息放入主线程队列中,配合主线程进行更新UI。

二、Handler一些特点
        handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
        它有两个作用: (1):  安排消息或Runnable在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
      
        Handler中分发消息的一些方法
        post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)
        以上post类方法允许你排列一个Runnable对象到主线程队列中,
        sendMessage类方法,允许你安排一个带数据的Message对象到队列中,等待更新.

三、Handler实例
      (1) 子类需要继承Handler类,并重写handleMessage(Message msg)方法, 用于接受线程数据
      以下为一个实例,它实现的功能为 :通过线程修改界面Button的内容

public class MyHandlerActivity extendsActivity {

Button button;

MyHandler myHandler;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.handlertest);

button = (Button) findViewById(R.id.button);

myHandler = new MyHandler();

// 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据

// Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象

// (2): 让一个动作,在不同的线程中执行.

// 它安排消息,用以下方法

// post(Runnable)

// postAtTime(Runnable,long)

// postDelayed(Runnable,long)

// sendEmptyMessage(int)

// sendMessage(Message);

// sendMessageAtTime(Message,long)

// sendMessageDelayed(Message,long)

// 以上方法以 post开头的允许你处理Runnable对象

//sendMessage()允许你处理Message对象(Message里可以包含数据,)

MyThread m = new MyThread();

new Thread(m).start();

}

/**

* 接受消息,处理消息 ,此Handler会与当前主线程一块运行

* */

class MyHandler extends Handler {

public MyHandler() {

}

public MyHandler(Looper L) {

super(L);

}

// 子类必须重写此方法,接受数据

@Override

public void handleMessage(Message msg) {

// TODO Auto-generated method stub

Log.d("MyHandler", "handleMessage......");

super.handleMessage(msg);

// 此处可以更新UI

Bundle b = msg.getData();

String color = b.getString("color");

MyHandlerActivity.this.button.append(color);

}

}

class MyThread implements Runnable {

public void run() {

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

// TODO Auto-generated catchblock

e.printStackTrace();

}

Log.d("thread.......", "mThread........");

Message msg = new Message();

Bundle b = new Bundle();// 存放数据

b.putString("color", "我的");

msg.setData(b);

MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI

}

}

1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。

在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,有Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,以为它需要绑定在主线程的消息队列中。

sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。

1.  //Handler处理子线程消息代码示例:

2.

3.  public class Activity01 extends Activity

4.  {

5.      //声明ProgressBar对象

6.      private ProgressBar m_ProgressBar;

7.      private ProgressBar m_ProgressBar2;

8.      private Button mButton01;

9.      protected static final int GUI_STOP_NOTIFIER = 0x108;

10.    protected static final int GUI_THREADING_NOTIFIER = 0x109;

11.    public int intCounter=0;

12.    /** Called when the activity is first created. */

13.    @Override

14.    public void onCreate(Bundle savedInstanceState)

15.    {

16.        super.onCreate(savedInstanceState);

17.        //设置窗口模式,,因为需要显示进度条在标题栏

18.        requestWindowFeature(Window.FEATURE_PROGRESS);

19.        setProgressBarVisibility(true);

20.        setContentView(R.layout.main);

21.

22.        //取得ProgressBar

23.        m_ProgressBar = (ProgressBar) findViewById(R.id.ProgressBar01);

24.        m_ProgressBar2= (ProgressBar) findViewById(R.id.ProgressBar02);

25.        mButton01 = (Button)findViewById(R.id.Button01);

26.

27.        m_ProgressBar.setIndeterminate(false);

28.        m_ProgressBar2.setIndeterminate(false);

29.

30.        //当按钮按下时开始执行,

31.        mButton01.setOnClickListener(new Button.OnClickListener()

32.        {

33.          @Override

34.          public void onClick(View v)

35.          {

36.            // TODO Auto-generated method stub

37.

38.              //设置ProgressBar为可见状态

39.              m_ProgressBar.setVisibility(View.VISIBLE);

40.              m_ProgressBar2.setVisibility(View.VISIBLE);

41.              //设置ProgressBar的最大值

42.              m_ProgressBar.setMax(100);

43.              //设置ProgressBar当前值

44.              m_ProgressBar.setProgress(0);

45.              m_ProgressBar2.setProgress(0);

46.

47.              //通过线程来改变ProgressBar的值

48.  new Thread(new Runnable() {

49.     public void run()

50.        {

51.     for (int i = 0; i < 10; i++)

52.        {

53.           try

54.           {

55.                 intCounter = (i + 1) * 20;

56.                 Thread.sleep(1000);

57.

58.            if (i == 4)

59.            {

60.            Message m = new Message();

61.

62.             m.what = Activity01.GUI_STOP_NOTIFIER;

63.            Activity01.this.myMessageHandler.sendMessage(m);

64.  //将message发送到消息队列

65.              break;

66.             }

67.            else

68.           {

69.           Message m = new Message();

70.           m.what = Activity01.GUI_THREADING_NOTIFIER;

71.           Activity01.this.myMessageHandler.sendMessage(m);

72. //将message发送到消息队列

73.                                }

74.                            }

75.                            catch (Exception e)

76.                            {

77.                                e.printStackTrace();

78.                            }

79.                        }

80.                    }

81.                }).start();

82.            }

83.        });

84.    }

85.

86.//通过匿名类复写Handler类中的handleMessage方法,用于接收传递到消息队列中的Message,并进行UI操作。

87.      Handler myMessageHandler = new Handler()

88.      {

89.        // @Override

90.          public void handleMessage(Message msg)

91.          {

92.              switch (msg.what)

93.              {

94.              //ProgressBar已经是对大值

95.              case Activity01.GUI_STOP_NOTIFIER:

96.                  m_ProgressBar.setVisibility(View.GONE);

97.                  m_ProgressBar2.setVisibility(View.GONE);

98.                  Thread.currentThread().interrupt();

99.                  break;

100.               case Activity01.GUI_THREADING_NOTIFIER:

101.                   if (!Thread.currentThread().isInterrupted())

102.                   {

103.                       // 改变ProgressBar的当前值

104.                       m_ProgressBar.setProgress(intCounter);

105.                       m_ProgressBar2.setProgress(intCounter);

106.

107.                       // 设置标题栏中前景的一个进度条进度值

108.                       setProgress(intCounter*100);

109.                       // 设置标题栏中后面的一个进度条进度值

110.                       setSecondaryProgress(intCounter*100);//

111.                   }

112.                   break;

113.               }

114.               super.handleMessage(msg);

115.          }

116.       };

117. }

以上的例子中,子线程只是对进度条的参数进行了变更,并将结果以message形式发送到消息队列中去,子线程的内部并未进行UI操作,而是在重写的Handler的handlerMessage方法中操作了UI界面。

2.传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。

Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。

1.  public class HandlerActivity extends Activity {

2.      /** Called when the activity is first created. */

3.      //声明两个按钮控件

4.      private Button startButton = null;

5.      private Button endButton = null;

6.      @Override

7.      public void onCreate(Bundle savedInstanceState) {

8.          super.onCreate(savedInstanceState);

9.          setContentView(R.layout.main);

10.        //根据控件的ID得到代表控件的对象,并未这两个按钮设置相应的监听器

11.        startButton = (Button)findViewById(R.id.startButton);

12.        startButton.setOnClickListener(new StartButtonListener());

13.        endButton = (Button)findViewById(R.id.endButton);

14.        endButton.setOnClickListener(new EndButtonListener());

15.

16.    }

17.    class StartButtonListener implements OnClickListener{

18.

19.        @Override

20.        public void onClick(View v) {

21.            //调用Handler的post方法,将要执行的线程对象添加到队列当中

22.            handler.post(updateThread);

23.        }

24.

25.    }

26.

27.    class EndButtonListener implements OnClickListener{

28.

29.        @Override

30.        public void onClick(View v) {

31.            handler.removeCallbacks(updateThread);

32.        }

33.

34.    }

35.    //创建一个Handler对象

36.    Handler handler  = new Handler();

37.    //将要执行的操作写在线程对象的run方法当中

38.    Runnable updateThread =  new Runnable(){

39.

40.        @Override

41.        public void run() {

42.            System.out.println("UpdateThread");

43.            //在run方法内部,执行postDelayed或者是post方法

44.            handler.postDelayed(updateThread, 3000);

45.        }

46.

47.    };

48.}

程序的运行结果就是每隔3秒钟,就会在控制台打印一行UpdateTread。这是因为实现了Runnable接口的updateThread对象进入了空的消息队列即被立即执行run方法,而在run方法的内部,又在3000ms之后将其再次发送进入消息队列中。

3. Handler和多线程

post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。

这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。SDK文档中也提供了相关说明:

When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the samepost or sendMessage methods as before, but from your new thread. The given Runnable or Message will than be scheduled in the Handler's message queue and processed when appropriate.

具体操作方法如下:

1.  public class HandlerTest2 extends Activity {

2.

3.      @Override

4.      protected void onCreate(Bundle savedInstanceState) {

5.          // TODO Auto-generated method stub

6.      super.onCreate(savedInstanceState);

7.      setContentView(R.layout.main);

8.      //打印了当前线程的ID

9.      System.out.println("Activity-->" + Thread.currentThread().getId());

10.    //生成一个HandlerThread对象

11.    HandlerThread handlerThread = new HandlerThread("handler_thread");

12.    //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start(),同时开启一个新线程;

13.    handlerThread.start();

14.   //将由HandlerThread获取的Looper传递给Handler对象,即由处于另外线程的Looper代替handler初始化时默认绑定的消息队列来处理消息。

15.    MyHandler myHandler = new MyHandler(handlerThread.getLooper());

16.    Message msg = myHandler.obtainMessage();

17.    //将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象

18.    Bundle b = new Bundle();

19.    b.putInt("age", 20);

20.    b.putString("name", "Jhon");

21.    msg.setData(b);

22.    msg.sendToTarget();  //将msg发送到myHandler

23.    }

24.

25.   //定义类

26.    class MyHandler extends Handler{

27.    public MyHandler(){

28.

29.    }

30.

31.    public MyHandler(Looper looper){

32.        super(looper);

33.    }

34.    @Override

35.    public void handleMessage(Message msg) {

36.        Bundle b = msg.getData();

37.        int age = b.getInt("age");

38.        String name = b.getString("name");

39.        System.out.println("age is " + age + ", name is" + name);

40.        System.out.println("Handler--->" + Thread.currentThread().getId());

41.        System.out.println("handlerMessage");

42.        }

43.    }

44.}

这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。

这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程。

androidHandler讲解的更多相关文章

  1. Android-Handler消息机制实现原理)(转)

    Android-Handler消息机制实现原理   一.消息机制流程简介 在应用启动的时候,会执行程序的入口函数main(),main()里面会创建一个Looper对象,然后通过这个Looper对象开 ...

  2. PHP与API讲解(一)

    了解API: 在使用与创建自己的API之前我们需要先了解什么是API! API代表应用程序编程接口,而接口指的是一个特定的服务.一个应用程序或者其他程序的公共模块. 理解SOA(面向服务的架构):SO ...

  3. 微信小程序(微信应用号)组件讲解

    这篇文章主要讲解微信小程序的组件. 首先,讲解新建项目.现在有句话:招聘三天以上微信小程序开发,这个估计只能去挖微信的工程师了.技术新,既然讲解,那我们就从开始建项目讲解. 打开微信web开发者工具, ...

  4. 免费公开课,讲解强大的文档集成组件Aspose,现在可报名

    课程①:Aspose.Total公开课内容:讲解全能型文档管理工具Aspose.Total主要功能及应用领域时间:2016-11-24 14:30 (暂定)报名地址:http://training.e ...

  5. EventBus总线讲解

    在我们公司经常用到总线,具体的总线是什么让我理解我也不清楚,但是在这几个月下来,我已经知道总线如何使用,现在加上示例讲解总线如何使用. 1. 首先我们的新建一个类,这个类其实是用于总线传递的模型 us ...

  6. FTP的搭建与虚拟目录作用<之简单讲解>

    操作系统:win7 VS2010编写WebService与在IIS的发布<之简单讲解>中我已经说了IIS安装与使用,不明白的可以跳过去看. 1.添加FTP站点 2. 3. 4. 5. zq ...

  7. Restful 介绍及SpringMVC+restful 实例讲解

    restful不是一个框架,称为一种编码更烦更贴切吧,其核心类位于spring-web.jar中,即RestTemplate.class restful是rpc通过http协议的一种实现方式,和web ...

  8. 实例讲解react+react-router+redux

    前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...

  9. 【Spring】SpringMVC入门示例讲解

    目录结构: // contents structure [-] SpringMVC是什么 Spring MVC的设计原理 SpringMVC入门示例 1,复制Jar包 2,Web.xml文件 3,My ...

随机推荐

  1. 字典树-百度之星-Xor Sum

    Xor Sum Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包括了N个正整数,随后 Prometheu ...

  2. [RxJS] Displaying Initial Data with StartWith

    You often need to render out data before you stream begins from a click or another user interaction. ...

  3. intel线程库tbb的使用

    [size=small]首先下载: http://www.threadingbuildingblocks.org/uploads/77/111/2.1/tbb21_20080605oss_win.zi ...

  4. 传感器仿真平台——UI绘制模块(二)

    这一章讲的是UI绘制模块 该模块的作用是将实验对象绘制出来,它可能是目标.传感器等等,由于事先并不知道会有哪些物体,也无法事先定义好某个对象该怎么画,以我懒人的性格,得了,就抛给用的人吧~喝前摇一摇, ...

  5. cookie 的Domain删除失败的问题

    最近接手一个老项目,项目中使用的是cookie来做的处理的,新增的时候cookie添加了域, 但是删除的时候没有添加域,导致删除cookie的时候一直失败!还有cookie的创建与删除,应该都必需经过 ...

  6. poj 3104 二分

    Drying Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12568   Accepted: 3243 Descripti ...

  7. Oracle11g R2学习系列 之五回闪

    Oracle里面有一个回闪的操作,这个貌似sql server是没有的.要使用这个功能,需要用到两个时间内部函数 TIMESTAMP和TO_TIMESTAMP.其中,函数TO_TIMESTAMP的语法 ...

  8. chart.js 示例

    一个简单的例子. 1.html代码 <div id="pie" style="width: 250px;float:left"> <h3> ...

  9. 安装python3.4

    1.http://www.python.org下载适合自己机型的镜像文件 2.一路“next”到底,安装python到C盘上 3.计算机-属性-高级系统设置-环境变量,将刚刚安装的python路径添加 ...

  10. 第一个程序 - Windows程序设计(SDK)001

    愉快的开始 让编程改变世界 Change the world by program 编译器安装 我们经常说的 VS 指的就是 Microsoft Visual Studio 的简称,它是微软开发工具的 ...