Android Handler机制

安卓中Handler的机制

Posted by ideastudio on August 25, 2016

Android的消息处理有三个核心类:Looper,Handler和Message

1. 消息类 Message

android.os.Message的主要功能是进行消息的封装,同时可以指定消息的操作形式,Message类定义的变量和常用方法如下:

  • public int what:变量,用于定义此Message属于何种操作
  • public Object obj:变量,用于定义此Message传递的信息数据,通过它传递信息
  • public int arg1:变量,传递一些整型数据时使用
  • public int arg2:变量,传递一些整型数据时使用
  • public Handler getTarget():普通方法,取得操作此消息的Handler对象

在整个消息处理机制中,message又叫task,封装了任务携带的信息和处理该任务的handler,虽然Handler有默认的构造方法,但首选的方法是通过Message.obtain()获取Message对象,这样在大多数情况下,避免了创建新对象而分配内存

2. 消息通道:Looper

在使用Handler处理Message时,需要Looper(通道)来完成。在应用启动的过程中,系统会自动在主线程调用Looper.prepareMainLooper()产生一个Looper对象,而在其他线程中如果要使用则必须调用Looper.prepare()方法,去实例化一个Looper,一个线程有且只能有一个Looper对象,在线程中传使用Looper的典型实例如一下:

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();//在当前线程中初始化一个Looper对象

        mHandler = new Handler() {//初始化一个Handler
            public void handleMessage(Message msg) {
                // process incoming messages here
                //收到消息后应做的处理
            }
        };
        //这里创建Message 然后发送消息
        Looper.loop();
        //一定要到最后才是调用Looper.loop() 因为里面有一个for(;;)循环 从MessageQueue中获取Message对象,然后再分发 交给Handler处理
    }
}

Lopper的prepare()方法代码

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

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
      //一个线程仅能创建一个Looper对象
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

Lopper的构造方法 在prepare()方法中有调用

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);//创建了一个MessageQueue实例用来存放Message
    mThread = Thread.currentThread();//获取当前线程的引用
}

Lopper的loop()方法,调用该方法后,Looper正式开始工作,不断从MessageQueue中取出队头的消息执行

public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        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 (;;) {
      //死循环 所以调用loop()方法后,之后的代码都不会执行
        Message msg = queue.next(); // might block
        if (msg == null) {
            // 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);
        }

        msg.target.dispatchMessage(msg);
        //消息的分发 msg.target其实就是发送消息的Handler对象

        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);
        }

        msg.recycleUnchecked();
    }
}

3. 消息操作类:Handler

Message封装了所有的消息,而这些消息的操作需要android.os.Handler类完成,Handler构造方法以及重要成员变量如下:

public class Handler {
final MessageQueue mQueue;
final Looper mLooper;//关联的Looper
final Callback mCallback;
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) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

    mLooper = Looper.myLooper();获取该线程关联的Looper对象
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
            //如果在创建handler之前没有调用Looper.prepare()则抛出异常
    }
    mQueue = mLooper.mQueue; // 将Looer初始化时创建的MessageQueue 关联起来
    mCallback = callback;
    mAsynchronous = async;
}
}

Looper.loop()方法中,循环取出MessageQueue中的消息,并进行分发,而Message相对应的dispatchMessage方法为

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
    //msg.callback 是一个Runnable对象 由postRunnable()传入,并将其包装为一条Message
        handleCallback(msg);
        // 上一条语句的实现为调用Runnable的run()方法 message.callback.run();
    } else {
      //直接调用handler的handleMessage()方法
        if (mCallback != null) {
            //如果创建Handler时有传入callback 则调用callback的handleCallback()方法,这种情况下不需要自己新建一个类继承Handler
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}