Android之Handler源代码深入解析

闲着没事。就来看看源代码,看看源代码的各种原理,会用仅仅是简单的,知道为什么才是最牛逼的。

Handler源代码分析那,从使用的步骤来边用边分析:

1.创建一个Handler对象:new Handler(getMainLooper(),this);

这是我经常使用的一个方式。getMainLooper是获取主线程的Looper。this则是实现CallBack的接口

看一下Handler的构造函数

public Handler() {

this(null, false);

}

public Handler(Callback callback) {

this(callback, false);

}

public Handler(Looper looper) {

this(looper, null, false);

}

public Handler(Looper looper, Callback callback) {

this(looper, callback, false);

}

@hide

public Handler(boolean async)
{

this(null,
async);

}

@hide

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

if (mLooper == null)
{

throw new RuntimeException(

"Can‘t create handler inside thread that has not called Looper.prepare()");

}

mQueue = mLooper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

@hide

public Handler(Looper looper, Callback callback, boolean async)
{

mLooper = looper;

mQueue = looper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

构造函数的最主要代码作用是參数的初始化赋值:

mLooper = looper;mQueue = looper.mQueue;mCallback =
callback;  mAsynchronous = async;

这四个參数是基本的參数了。

2.创建一个Message。     Message msg = handler.obtainMessage();

直接调用Handler的源代码:

public final Message obtainMessage()

{

return Message.obtain(this);

}

Message中得源代码:

public static Message obtain(Handler h) {

Message m = obtain();

m.target = h;

return m;

}

public static Message obtain() {

synchronized (sPoolSync)
{

if (sPool != null)
{

Message m = sPool;

sPool = m.next;

m.next = null;

m.flags = 0; // clear in-use flag

sPoolSize--;

return m;

}

}

return new Message();

}

这里Message是复用的概念,最大可以保持

private static final int MAX_POOL_SIZE =
50;

50个Message的对象。

sPool变量相当于当前的空的没有被使用的Message,通过转换,将当前这个空Message给返回出去。

Message在使用完之后会被回收的。在以下会有提到。

3.给Message赋值。并发送Message :    msg.what = 100 ; handler.sendMessage(msg);

what是Message中得一个储值变量。

发送Message则在Handler中得终于指向是下面源代码:

private boolean enqueueMessage(MessageQueue queue, Message
msg, long uptimeMillis) {

msg.target = this;

if (mAsynchronous)
{

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

oK。sendMessage给发送给了MessageQueue类。看MessageQueue怎么处理的。

boolean enqueueMessage(Message msg, long when) {

?...........

if (p == null ||
when == 0 || when < p.when) {

// New head, wake up the event queue if blocked.

msg.next = p;

mMessages = msg;

needWake = mBlocked;

} else {

// Inserted within the middle of the queue.  Usually we don‘t have to wake

// up the event queue unless there is a barrier at the head of the queue

// and the message is the earliest asynchronous message in the queue.

needWake = mBlocked && p.target == null &&
msg.isAsynchronous();

Message prev;

for (;;) {

prev = p;

p = p.next;

if (p == null ||
when < p.when) {

break;

}

if (needWake && p.isAsynchronous()) {

needWake = false;

}

}

msg.next = p; // invariant: p == prev.next

prev.next = msg;

}

if (needWake) {

nativeWake(mPtr);

}

}

.......

}

截取了中间重要的代码说一下。

这个是用来干嘛的??

事实上就是用来排序的,我们知道的是Message有延迟的消息,延迟消息的时间都是不一样的。when是有大小的,将后运行的Message放到后面。

MessageQueue不是使用一个集合啊或者使用数组去存放的Message,真正排序的是Message的next变量。next变量存放的是当前Message的下一个Message。

发送之后就运行了一个原生的方法nativeWake,这个在这儿就不去探究了。

4.handler消息的处理回调Callback.

public static void loop()
{

........

for (;;) {

Message msg = queue.next(); // might block

?    ?    ?.....

msg.target.dispatchMessage(msg);

?    ?    ?       ?    ??.......

msg.recycleUnchecked();

}

?

?    ?......

}

这个那是Looper种的源代码。loop就是循环取MessageQueue中得Message的方法。我去掉了代码,我们能够看到调用了Messa得target变量,这个变量存放的就是Handler,dispatchMessage就是用来分发Message的方法了。看DispatchMessage的源代码:

public void dispatchMessage(Message
msg) {

if (msg.callback != null)
{

handleCallback(msg);

} else {

if (mCallback != null)
{

if (mCallback.handleMessage(msg))
{

return;

}

}

handleMessage(msg);

}

}

这个就少了非常多了啊。

看到了把,回调了callback。

这样就完毕了整个循环流程。

说一下上面的

msg.recycleUnchecked()方法。

相同,看源代码:

void recycleUnchecked() {

// Mark the message as in use while it remains in the recycled object pool.

// Clear out all other details.

flags = FLAG_IN_USE;

what = 0;

arg1 = 0;

arg2 = 0;

obj = null;

replyTo = null;

sendingUid = -1;

when = 0;

target = null;

callback = null;

data = null;

synchronized (sPoolSync)
{

if (sPoolSize < MAX_POOL_SIZE)
{

next = sPool;

sPool = this;

sPoolSize++;

}

}

}

从方法名上能够知道这个是用来回收Message的。

在Message使用完成之后,不是将MEssage对象销毁,而是存放起来,将其下次反复使用。

Handler执行大概流程就是这种了。

Looper的类的源代码分析,回头再解析。

Android开发交流群:417270671

我的github地址: https://github.com/flyme2012

时间: 2024-10-23 13:02:45

Android之Handler源代码深入解析的相关文章

android之handler机制深入解析

一.android中需要另开线程处理耗时.网络的任务,但是有必须要在UI线程中修改组件.这样做是为了: ①只能在UI线程中修改组件,避免了多线程造成组件显示混乱 ②不使用加锁策略是为了提高性能,因为android中经常使用多线程. handler就是为了解决在多个线程之间的通信问题. 二.基本使用: 1 package com.dqxst.first.multithread; 2 3 import android.app.Activity; 4 import android.os.Bundle;

深入解析Android中Handler消息机制

Android提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange).Handler消息机制可以说是Android系统中最重要部分之一,所以,本篇博客我们就来深入解析Android中Handler消息机制. Handler的简单使用 为什么系统不允许子线程更新UI 因为的UI控件不是线程安全的. 如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那为什么不对UI控件的访

Android 开源框架Universal-Image-Loader完全解析(三)---源代码解读

本篇文章主要是带大家从源码的角度上面去解读这个强大的图片加载框架,自己很久没有写文章了,感觉生疏了许多,距离上一篇文章三个月多了,确实是自己平常忙,换了工作很多东西都要去看去理解,然后加上自己也懒了,没有以前那么有激情了,我感觉这节奏不对,我要继续保持以前的激情,正所谓好记性不如烂笔头,有时候自己也会去翻看下之前写的东西,我觉得知识写下来比在脑海中留存的更久,今天就给大家来读一读这个框架的源码,我感觉这个图片加载框架确实写的很不错,读完代码自己也学到了很多.我希望大家可以先去看下Android

Android的Handler深入解析

1.概述 前面写过一篇文章<Android中的消息机制>简单分析了异步消息机制,本文将深入解读Handler的原理. 2.基本概念 单线程模型中的Message.Handler.Message Queue.Looper之间的关系: Handler获取当前线程的Looper对象,Looper用来从存放Message的MessageQueue中取出Message,再由Handler进行Message的分发和处理. (1)Message Queue(消息队列) 用来存放通过Handler发布的消息,

Android 开源项目源码解析(第二期)

Android 开源项目源码解析(第二期) 阅读目录 android-Ultra-Pull-To-Refresh 源码解析 DynamicLoadApk 源码解析 NineOldAnimations 源码解析 SlidingMenu 源码解析 Cling 源码解析 BaseAdapterHelper 源码分析 Side Menu.Android 源码解析 DiscreteSeekBar 源码解析 CalendarListView 源码解析 PagerSlidingTabStrip 源码解析 公共

Android异步加载全解析之使用多线程

异步加载之使用多线程 初次尝试 异步.异步,其实说白了就是多任务处理,也就是多线程执行,多线程那就会有各种问题,我们一步步来看,首先,我们创建一个class--ImageLoaderWithoutCaches,从命名上,大家也看出来,这个类,我们实现的是不带缓存的图像加载,不多说,我们再创建一个方法--showImageByThread,通过多线程来加载图像: /** * Using Thread * @param imageView * @param url */ public void sh

Android App的源代码

Android App的源代码: --------------------------------------------------------------------------------------------- // myActivity.java package com.misoo.pk01; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Co

Android 开源框架Universal-Image-Loader完全解析(二)--- 图片缓存策略详解

本篇文章继续为大家介绍Universal-Image-Loader这个开源的图片加载框架,介绍的是图片缓存策略方面的,如果大家对这个开源框架的使用还不了解,大家可以看看我之前写的一篇文章Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用,我们一般去加载大量的图片的时候,都会做缓存策略,缓存又分为内存缓存和硬盘缓存,我之前也写了几篇异步加载大量图片的文章,使用的内存缓存是LruCache这个类,LRU是Least Recently Used 近

错误:Only the original thread that created a view hierarchy can touch its views——Handler的深入解析

这个错误很常见,基本上写线程操作都遇到过这个错误.根本原因是view控件的线程安全问题,通俗点讲就是所有的更新UI操作都需要在主线程(也就是UI线程中完成),而不能在新开的子线程中操作. 基本思路:既然子线程需要更新UI,但子线程自身又不能完成任务,所以只能通过建立一个通信机制,当子线程需要更新UI时,发消息通知主线程并将更新UI的任务post给主线程,让主线程来完成分内的UI更新操作.这个机制是什么呢?就是Handler.Handler 从属于谁?当然是主线程.每个线程都有自己的handler