Handler学习笔记

public class Handler {
    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;
    final boolean mAsynchronous;
    IMessenger mMessenger;                      
/*参数中不带looper的构造方法会回调Handler(Callback callback, *boolean *async) 这个构造方法*/
public Handler() {  this(null, false);  }
public Handler(Callback callback){ this(callback, false);}
public Handler(boolean async) {  this(null, async);  }

/*参数中带looper的构造方法会回调Handler(Looper looper,Callback *callback, boolean *async) 这个构造方法*/
public Handler(Looper looper) {this(looper, null, false);}
public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    }

在看Handler(Callback callback, boolean async){}方法

public Handler(Callback callback, boolean async) {

        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
  //这句话的意思是 handler要设置为静态,否则可能会发生内存泄露                  
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
        mLooper = Looper.myLooper();
        if (mLooper == null) {
/*没有Looper.prepare()的线程是不能创建handler的即需要调用  
*Looper.prepare()对mLooper 进行初始化*/
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
/* 重点:直接把关联looper的MQ作为自己的MQ,因此它的消息将发送到关联*looper的MQ上*/
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

1)Looper.prepare()

public final class Looper {
  static final ThreadLocal<Looper> sThreadLocal = new  
  ThreadLocal<Looper>();
  private static Looper sMainLooper; 
  final MessageQueue mQueue;
  final Thread mThread;
private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

public static void prepare() {
        prepare(true);
    }

private static void prepare(boolean quitAllowed) {
/*ThreadLocal用于线程间的数据隔离,每个线程内部维护一个独立内存区域,数据为线程独有,不共享>*/
     if (sThreadLocal.get() != null) {
     //一个线程只能有一个looper
     throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

 public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
  }
    }

由上述代码可知,Looper.prepare()是一个将线程转换为looperThread的过程,为了迎合一个thread只能有一个looper对象这一原则,首先会校验当前线程是否已经有looper对象,有则抛出异常,没有则创建looper对象,并把它存储在sThreadLocal中,以供looper.myLooper()获取当前线程的looper对象。

2)Looper.loop()

  public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
        //looper没有初始化,即没有调用了looper.prepare().
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
   //MessageQueue 中没有Message 时,退出消息队列读取消息的循环
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
/*由message的target(即handler)来处理从MessageQueue中取出的 *message*/
            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
// 回收message资源
            msg.recycle();
        }
    }

调用loop方法后,Looper线程就开始真正工作了,它不断从自己的MQ中取出队头的消息(也叫任务)执行。

3)looper的其他方法

//这个方法不需要我们自己调用,系统会自动调用
    public static void prepareMainLooper() {
/* prepare(false)结合Messagequeue的quit(boolean)方法可知主线程是不能 *被quit的*/
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

4)LooperThread 样板

public class LooperThread extends Thread {
    private Handler handler1;
    private Handler handler2;
    @Override
    public void run() {
        // 将当前线程初始化为Looper线程
        Looper.prepare();
        // ...其他处理,如实例化handler
        handler1 = new Handler();
        handler2 = new Handler();
        // 开始循环处理消息队列
        Looper.loop();
    }
}

由此可知:一个线程可以有多个Handler,但是只能有一个Looper!

5)handler发送消息
post(Runnable)
postAtTime(Runnable, long)
postDelayed(Runnable, long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message, long)
sendMessageDelayed(Message, long)这些方法向MQ上发送消息了
这里介绍一下post(Runnable)

    public final boolean post(Runnable r){
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
    }

    public final boolean sendMessageDelayed(Message msg, 
        long  delayMillis)           
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis()    +  delayMillis);
    }

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

由上述代码可知post发出的Runnable对象最后都被封装成message对象,在这个过程中由getPostMessage(r)将runnable封装成message的callback,再由handler的enqueueMessage()调用MessageQueue的enqueueMessage()方法 将消息添加到消息队列中。

6)handler处理消息

 // 处理消息,该方法在looper.loop()中被调用
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
 // 如果message设置了callback,即runnable消息,处理callback!
            handleCallback(msg);
        } else {
// 如果handler本身设置了(Handler.Callback)callback,则执行callback
            if (mCallback != null) {
/* 这种方法允许让activity等来实现Handler.Callback接口,避免了自己编写*handler重写handleMessage方法。见http://alex-yang-xiansoftware-*com.iteye.com/blog/850865 */
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
// 如果message没有callback,则调用handler的钩子方handleMessage
            handleMessage(msg);
        }
    }

    // 处理runnable消息
    private final void handleCallback(Message message) {
        message.callback.run();  //直接调用run方法!
    }
    // 由子类实现的钩子方法
    public void handleMessage(Message msg) {
    }

    public interface Callback {
        public boolean handleMessage(Message msg);
    }

7)ThreadLocal理解http://blog.youkuaiyun.com/qjyong/article/details/2158097

8)总结:
1. handler要设置为静态,否则可能会发生内存泄露
2. 线程创建handler之前必须调用looper.prepare()对looper初始化
3. looper.loop()开始从消息队列取出队头message交给handler的diapatchMessage()处理消息
4. handler.post()发出的Runnable对象最后都被封装成message对象
5. 一个线程可以有多个Handler,但是只能有一个Looper对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值