Handler的使用(二)
2012-05-13 01:03 ...平..淡... 阅读(446) 评论(0) 编辑 收藏 举报简单描述如下: Looper类 是用来封装消息循环和消息队列的一个类。 handler 其实可以看做是一个工具类,通过Looper类向消息队列中插入消息,然后通过Looper类从消息队列中提取消息让handler类来处理消息的。
ps:可以通过Loop.myLooper()可以得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。默认情况下建立的handler都是与当前线程的looper相关的,但是也可以获取主线程的looper,然后在子线程中建立主线程的handler
HandlerThread 类实现了循环处理消息的功能,所以在本文程序中我没有定义Looper类对象,直接通过HandlerThread的getLooper方法获取。
MessageQueue负责存储有关某一个线程(通常是主线程)的所有消息,而Looper则负责管理消息队列,Handler负责向消息队列发送消息和处理消息~
分析以下两种情况:
1.handler与主activity在同一个线程的情况:
使用post方法来把线程对象放到消息队列中,是直接调用线程对象的run方法,其实没有开启新的线程. 因为线程都需要通过start方法来启动,而handler没有通过线程的start方法来启动线程,所以它们是处于同一线程。
2.创建子线程的情况:
生成HandlerThread类的对象,然后调用start方法,产生新的线程,然后再创建Handler对象(MyHandler继承自Handler)。 MyHandler myHandler = new MyHandler(handlerThread.getLooper());
之后操作同"handler的使用(一)"。
下面详解转自http://byandby.iteye.com/blog/825071
比如我想在子线程中定义一个字符串,然后通过发消息的方式,Message把这个字符串发送给主线程也就是UI线程,让UI线程来设置这个TextView的值为我们刚刚在子线程中定义的字符串。或者我想在子线程中开启音乐服务,或者把它停止该怎么做呢?要知道怎么做先让我们了解一下这几个对象吧!它们分别是 MessageQueue、Handler、Looper。 在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。 1.Message Queue Message Queue是一个消息队列,用来存放通过Handler发布的消息。消息队列通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。如果没有消息队列对象则会抛出空指针异常。Android在第一次启动程序时会默认会为UI thread创建一个关联的消息队列,用来管理程序的一些上层组件,如activities,broadcast receivers 等等。你可以在自己的子线程中创建Handler与UI thread通讯。也就是说我们程序一启动我们的UI线程也就是主线程就会有一个消息队列,而如果我们自己另外开启的一个子线程就不会有MessageQueue(消息队列)对象。这一点大家务必知道。 2. Handler 通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例。每个Handler都会与唯一的一个线程以及该线程的消息队列关联。当你创建一个新的Handler时候,默认情况下,它将关联到创建它的这个线程和该线程的消息队列。也就是说,如果你通过Handler发布消息的话,消息将只会发送到与它关联的这个消息队列,当然也只能处理该消息队列中的消息。这里大家就得理解一下了 也就是说我们一个Handler对应一个线程以及附属于该线程的消息队列。 3. Looper Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。 1)可以通过Looper类 的静态方法Looper.myLooper()得到当前线程的Looper实例,如果当前线程未关联一个Looper实例,该方法将返回空(null)它不会抛空指针异常。 2)可以通过静态方法Looper. getMainLooper()方法得到主线程的Looper实例。这里需要注意一下,主线程默认是有一个Looper对象的,但是我们自己定义的子线程没有的。那么我们怎么在子线程中得到Looper对象呢?如果一个线程中调用Looper.prepare(),那么系统就会自动的为该线程建立一个消息队列,然后调用Looper.loop();之后就进入了消息循环,之后就可以发消息、取消息、和处理消息。这个如何发送消息和如何处理消息可以在其他的线程中通过Handle来做,但前提是我们的Handler知道这个子线程的Looper,但是你如果不是在子线程运行Looper.myLooper(),一般是得不到子线程的looper的。
比上面解释劲爆的多的多的解释!!!!
发现的太晚了,留着上面那种解释,来对比
Handler
消息的封装者和处理者,handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现;将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法对其进行处理。
Message
消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message。Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。除了上面这种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。
MessageQueue
是一种数据结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。
Looper
是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象。创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。
使用HandlerThread来简单进行程序演示
step1:新建android工程,命名为HandlerTest2.
step3:主Activity程序..
1 HandlerTest2 2 package com.cb.handler; 3 4 import android.app.Activity; 5 import android.os.Bundle; 6 import android.os.Handler; 7 import android.os.HandlerThread; 8 import android.os.Looper; 9 import android.os.Message; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.widget.Button; 13 import android.widget.ProgressBar; 14 15 public class HandlerTest2 extends Activity { 16 @Override 17 public void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.main); 20 // handler.post(r); 21 22 //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由android应用程序框架提供。 23 HandlerThread handlerThread = new HandlerThread("Handler_Thread"); 24 //在使用HandlerThread的getLooper方法之前,必须先调用该类的start方法,否则getLooper方法取出的值是空值。 25 handlerThread.start(); 26 27 // 28 MyHandler myHandler = new MyHandler(handlerThread.getLooper()); 29 Message msg = myHandler.obtainMessage(); 30 31 Bundle bundle = new Bundle(); 32 bundle.putString("name", "cb"); 33 bundle.putInt("age", 20); 34 msg.setData(bundle); 35 36 //将msg对象发送到目标对象,所谓的目标对象就是生成该msg对象的Handler对象。 37 msg.sendToTarget(); 38 39 System.out.println("activity---->"+Thread.currentThread().getId()); 40 System.out.println("activity---->"+Thread.currentThread().getName()); 41 } 42 43 class MyHandler extends Handler { 44 public MyHandler() {} 45 46 public MyHandler(Looper looper) { 47 super(looper); 48 } 49 50 @Override 51 public void handleMessage(Message msg) { 52 System.out.println("handler------>"+Thread.currentThread().getId()); 53 System.out.println("handler------>"+Thread.currentThread().getName()); 54 } 55 56 } 57 }
step4:图示结果
因为handler(id号与name值) 和activity的不同,说明确实创建了新的子线程。
continue my dream...