Android——Handler源码分析

从源码分析Handler

1、APP的入口 ActivityThread 类的 main()方法,在main方法中调用了 Looper.prepareMainLooper();

public static void main(String[] args) {
    //....省略

    //Looper的初始化
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    //开始消息轮循
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

2、Looper.prepareMainLooper()中调用了 prepare(false);方法

        public static void prepareMainLooper() {
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                sMainLooper = myLooper();
            }
        }

        //quitAllowed 表示是否可以退出此 Looper
        private static void prepare(boolean quitAllowed) {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }

            //ThreadLocal和 Looper的绑定,即当前线程和Looper绑定
            sThreadLocal.set(new Looper(quitAllowed));
        }

3、prepare(false)方法中调用 sThreadLocal.set(new Looper(quitAllowed));
完成了 ThreadLocal和 Looper的绑定,即当前线程和Looper绑定。

sThreadLocal.set(new Looper(quitAllowed));

//sThreadLocal是Looper的静态成员变量
static final ThreadLocal sThreadLocal = new ThreadLocal();

4、Looper的构造方法中 初始化了 MessageQueue

        private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }

5、以上四步完成了 Looper、MessageQueue和ThreadLocal的初始化,

6、在main()方法的最后调用了 Looper.loop()方法,这个方法内部是一个死循环,这个时候主线程的消息处理机制就运行起来了。

public static void loop() {
    final Looper me = myLooper();
    //...省略
    for (;;) {
        Message msg = queue.next(); // might block可能阻塞,queue.next()取出消息
        //...省略
        final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        final long end;
        try {
            //在这里由target(即handler)分发消息
            msg.target.dispatchMessage(msg);

            end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        //...省略
        msg.recycleUnchecked();
    }
}

7、创建Handler对象,在handler的构造方法中,如果 mLooper 为空,则会抛出异常。

注意:在子线程中创建Handler对象时,要先调用 Looper.prepare()方法,完成Looper的初始化,从源码中分析,每个线程只允许有一个Looper。

public Handler() {
    if (FIND_POTENTIAL_LEAKS) {
        final Class 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();
    if (mLooper == null) {
        throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = null;
}

8、Handler发送消息,最终会调用到sendMessageAtTime(Message msg, long uptimeMillis)方法,uptimeMillis参数则表示发送消息的时间,它的值等于自系统开机到当前时间的毫秒数再加上延迟时间,SystemClock.uptimeMillis() + delayMillis。如果你调用的不是sendMessageDelayed()方法,延迟时间就为0。

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);//把消息加入到消息队列(消息入队的方法)
}



9、入队其实就是将所有的消息按时间来进行排序
//把消息加入到消息队列(消息入队的方法)
enqueueMessage(queue, msg, uptimeMillis);

10、消息出队方法即 Message msg = queue.next();
// might block可能阻塞,queue.next()取出消息。

消息处理即 msg.target.dispatchMessage(msg);
//在这里由target(即handler)分发消息。

        public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }

11、一个标准的异步线程 消息处理写法:

        class LooperThread extends Thread {
              public Handler mHandler;

              public void run() {
                  Looper.prepare();

                  mHandler = new Handler() {
                      public void handleMessage(Message msg) {
                          // process incoming messages here
                      }
                  };

                  Looper.loop();
              }
          }

12、另外除了发送消息之外,我们还有以下几种方法可以在子线程中进行UI操作:
1. Handler的post()方法
2. View的post()方法(内部实际上也是调用的 Handler的post()方法)
3. Activity的runOnUiThread()方法(内部实际上也是调用的 Handler的post()方法)

handler.post的源码:

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

private final Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;  //直接把传入的Runnable对象作为callback
    return m;
}

在dispatchMessage()方法中,
if (msg.callback != null) {
    handleCallback(msg);
}

private static void handleCallback(Message message) {
    message.callback.run();//即由Runnable自行处理message
}

Android中为什么主线程不会因为Looper.loop()里的死循环卡死

参考:https://www.zhihu.com/question/34652589

HandlerThread——可循环子线程

1、HandlerThread继承自Thread,它的run()中通过Looper.prepare()创建了消息队列,并通过Looper.loop()开启了消息循环。

        @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();
            mTid = -1;
        }

2、使用方法:

    //1、创建HandlerThread
    HandlerThread  handlerThread = new HandlerThread("workHandlerThread");
    handlerThread.start();

    //2、获取获取HandlerThread的Looper
    Looper looper = handlerThread.getLooper();

    //3、 创建Handler,通过Looper初始化
    Handler  childHandler = new Handler(looper,mCallback);

    //4、投放异步耗时任务到HandlerThread中
    // childHandler.sendEmptyMessage(0);

    //4、关闭消息队列,释放线程资源
    handlerThread.quit() ;
public class HandlerThreadTestActivity extends BaseActivity {
    private HandlerThread handlerThread;//子线程
    private Handler childHandler;//与子线程关联的Handler
  
    private Handler.Callback callback = new Handler.Callback() {
        //子线程处理耗时操作的回调
        @Override
        public boolean handleMessage(Message msg) {
            return false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread_test);
        initHandlerThread();
        getData();
    }

    private void initHandlerThread() {
        handlerThread = new HandlerThread("child_thread");  //构造参数为子线程的线程名
        handlerThread.start();//开启子线程
        childHandler = new Handler(handlerThread.getLooper(),callback);//初始化子线程的Handler
    }

    private void getData() {
        //投放异步耗时任务到HandlerThread中
        childHandler.sendEmptyMessage(0);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //释放资源
        handlerThread.quit() ;
    }
}

3、使用HandlerThread的好处
3.1、HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
3.2、HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
3.3、开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理

4、HandlerThread的使用情景

5、Handler 和 Timer

IntentService 内部封装的就是 HandlerThread

IntentService 是继承于 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

所有请求都在一个单线程中(HandlerThread),不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。

使用IntentService的好处:
1、我们省去了在 Service 中手动开线程的麻烦,
2、当操作完成时,我们不用手动停止 Service。

你可能感兴趣的:(Android——Handler源码分析)