Android中关于Handler Looper理解

在Android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作。

为了达到这个目的Android设计了handler Looper这个系统框架。

首先讲解在主线程中使用Handler时源码跟踪过程。

正常在activity的oncreate函数中定义个handler,这种情况下就是默认的主线程的handler,并去复写该类的handleMessage()函数。

private final Handler mMessageHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        ....;
    }
}

在这里new 了一个Handler类,跟入系统代码

106    /**
107     * Default constructor associates this handler with the {@link Looper} for the
108     * current thread.
109     *
110     * If this thread does not have a looper, this handler won‘t be able to receive messages
111     * so an exception is thrown.
112     */
113    public Handler() {
114        this(null, false);
115    }
188    public Handler(Callback callback, boolean async) {
189        if (FIND_POTENTIAL_LEAKS) {
190            final Class<? extends Handler> klass = getClass();
191            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
192                    (klass.getModifiers() & Modifier.STATIC) == 0) {
193                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
194                    klass.getCanonicalName());
195            }
196        }
197
198        mLooper = Looper.myLooper();
199        if (mLooper == null) {
200            throw new RuntimeException(
201                "Can‘t create handler inside thread that has not called Looper.prepare()");
202        }
203        mQueue = mLooper.mQueue;
204        mCallback = callback;
205        mAsynchronous = async;
206    }

最后需要对mQueue;mCallback;mAsynchronous这三个变量赋值。
这里注意 mLooper = Looper.myLooper(); 对mLooper的初始化。这里进入了Looper类

191    public static @Nullable Looper myLooper() {
192        return sThreadLocal.get();
193    }
68    // sThreadLocal.get() will return null unless you‘ve called prepare().
69    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
92    private static void prepare(boolean quitAllowed) {
93        if (sThreadLocal.get() != null) {
94            throw new RuntimeException("Only one Looper may be created per thread");
95        }
96        sThreadLocal.set(new Looper(quitAllowed));
97    }
98

最后new Looper(quitAllowed) 在这里在当前thread中新建了一个Looper对象(所以从这里可以看出来Looper是属于当前thread的)。
正常在我们自己new的线程中都需要调用Looper.prepare();语句来为当前线程new一个looper对象。但是对于UI线程中创建的looper是不需要的,因为在初始化UI线程时就已经写好了。

正常UI线程初始化时调用prepareMainLooper这个函数。

99    /**
100     * Initialize the current thread as a looper, marking it as an
101     * application‘s main looper. The main looper for your application
102     * is created by the Android environment, so you should never need
103     * to call this function yourself.  See also: {@link #prepare()}
104     */
105    public static void prepareMainLooper() {
106        prepare(false);
107        synchronized (Looper.class) {
108            if (sMainLooper != null) {
109                throw new IllegalStateException("The main Looper has already been prepared.");
110            }
111            sMainLooper = myLooper();
112        }
113    }

对于一般的子线程需要继续调用Looper.loop来启动loop循环进行消息发送。
而同样对于UI线程的looper同样是在初始化过程中已经调用好了。

128    public static void loop() {
129        final Looper me = myLooper();
130        if (me == null) {
131            throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");
132        }
133        final MessageQueue queue = me.mQueue;
..............
142        for (;;) {
143            Message msg = queue.next(); // might block
144            if (msg == null) {
145                // No message indicates that the message queue is quitting.
146                return;
147            }
。。。。。。。。。。
158            msg.target.dispatchMessage(msg);

在这个loop()函数中就能真正看到消息循环机制。在一个死循环中for(;;)不断从queue消息队列中获取messager,如果没有将阻止在该端口等待下一个messager。
在获取一个消息后则放入message中的targe中进行消息分发。

这里的target其实就是最开始在封装一个message进行发送时传入的handler,所以从这里也可以看出,最后消息还是通过handler传入到它所在的线程中调用handleMessage()进行处理。

message.java 的成员变量:

public final class Message implements Parcelable {
   public int what;
   public int arg1;
   public int arg2;
   public Object obj;
   public Messenger replyTo;
   public int sendingUid = -1;
   /*package*/ static final int FLAG_IN_USE = 1 << 0;
   /** If set message is asynchronous */
   /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
   /** Flags to clear in the copyFrom method */
   /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
   /*package*/ int flags;
   /*package*/ long when;
   /*package*/ Bundle data;
   /*package*/ Handler target
   /*package*/ Runnable callback;
   // sometimes we store linked lists of these things
   /*package*/ Message next;

。。。。

时间: 2024-08-05 02:07:09

Android中关于Handler Looper理解的相关文章

Android中的Handler, Looper, MessageQueue和Thread

Android中的Handler, Looper, MessageQueue和Thread 前几天,和同事探讨了一下Android中的消息机制,探究了消息的发送和接收过程以及与线程之间的关系.虽然我们经常使用这些基础的东西,但对于其内部原理的了解,能使我们更加容易.合理地架构系统,并避免一些低级错误. 对于这部分的内容,将分成4小节来描述: 1.职责与关系 2.消息循环 3.线程与更新 4.几点小结 ------------------------------------------------

Android中的Handler, Looper, MessageQueue和Thread对应关系

1) 作用 Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理. Handler:处理者,负责Message的发送及处理.使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等. MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行.当然,存放Message并非实际意义的保存,而是将Messag

深入源码解析Android中的Handler,Message,MessageQueue,Looper

本文主要是对Handler和消息循环的实现原理进行源码分析,如果不熟悉Handler可以参见博文< Android中Handler的使用>,里面对Android为何以引入Handler机制以及如何使用Handler做了讲解. 概括来说,Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制.我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功能.但

Android中的Handler的机制与用法详解

概述: 很多android初学者对android 中的handler不是很明白,其实Google参考了Windows的消息处理机制, 在Android系统中实现了一套类似的消息处理机制.在下面介绍handler机制前,首先得了解以下几个概念:     1. Message 消息,理解为线程间通讯的数据单元.例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程.     2. Message Queue 消息队列,用来存放通过Handler发布的消息,按照先

Android中的Handler

当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放在Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序就会挂掉.Handler就是把这些功能放到一个当初的线程里执行,与Activity互不影响. 一.Handler的定义:  Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在handler的线程中来接收.处理该消

Android中利用Handler实现消息的分发机制(三)

在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而如果在子线程中需要去使用Handler的时候,我们就需要显式地去调用Looper的 prepare方法和loop方法,从而为子线程创建其唯一的Looper. 具体代码如下: class LooperThread extends Thread { public Handler mHandler; public void run()

Android中的Handler的具体用法

Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行.Android利用Handler来实现UI线程的更新的. Handler是Android中的消息发送器,其在哪个Activity中创建就属于且紧紧属于该Activity.还可以说其在哪个线程中new的,就是那个线程的Handler. Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的U

android中的Handler和Callback机制

android中的Handler和Callback机制 - - ITeye技术网站 Handler主要用来在线程之间的通信的机制.如在Activity或Service中需要接受其他线程的消息,则在需要接收消息的Activity或Service中需要实现Handler.Callback接口,实现这个接口的: Java代码 ? public?boolean?handleMessage(?Message?inMessage?)?:?? public boolean handleMessage( Mes

Android中使用Handler造成内存泄露的分析和解决

什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收:另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收. Android中使用Handler造成内存泄露的原因 Handler mHand