Android提供了Handler来进行简单的线程间通信,通常我们在异步线程中做一些耗时的操作,然后通过Handler发送消息,在主线程中通过Handler的handleMessage方法去更新UI。我们先来看一下Handler的构造方法。
public Handler() {
this(null, false);
}
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();//初始化成员mLooper
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;//初始化成员mQueue
mCallback = callback;
mAsynchronous = async;
}
看一下Looper.java的部分代码
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
static final ThreadLocal sThreadLocal = new ThreadLocal();
Handler的构造方法通过Looper的static方法myLooper从一个类型为ThreadLocal的static变量sThreadLocal中get一个Looper实例。
ThreadLocal.java
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;//第一次返回null
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);//计算桶的位置
table[i] = new Entry(firstKey, firstValue);//将value包装为Entry放入table
size = 1;
setThreshold(INITIAL_CAPACITY);
}
static class Entry extends WeakReference> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);
value = v;
}
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocal的get和set方法都是通过一个ThreadLocalMap进行的,这个ThreadLocalMap与当前Thread关联在一起,通过当前Thread可以get到这个Map,这个Map的内部实际是一个数组,数组元素是Entry类型,Entry继承WeakReference,它有一个成员value,这样Entry就相当于一个键值对。
回来看Looper的prepare方法
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//第一次调用get会crateMap,并返回null
//第二次调用get将返回非null,这里会抛出一个异常,所以prepare方法每个线程只能调用一次
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));//set方法将sTreadLocal作为key,Looper实例作为value放入ThreadLocalMap
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);//new一个MessageQueue实例
mThread = Thread.currentThread();//将成员mThread初始化为当前Thread
}
从以上分析可以得出结论,在某个线程中new一个Handler之前必须调用Looper的prepare方法,初始化一个与当前线程绑定的Looper实例。
通常我们在使用Handler时是直接在主线程new一个Handler,那么是什么时候调用了Looper的prepare方法呢?
我们经常看到如下的堆栈信息,Android应用进程启动时会调用ActivityThread的main方法,这也是普通java程序的入口。
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke!(Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
ActivityThread.java
public static void main(String[] args) {
//忽略了一些代码
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
}
public static void prepareMainLooper() {
prepare(false);//这里调用了prepare方法
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();//初始化静态变量sMainLooper
}
}
private static Looper sMainLooper;
private void attach(boolean system) {
//忽略了部分代码
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
try {
mInstrumentation = new Instrumentation();
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
}
因为system传进来的是false我们暂时只看上面一部分。
RuntimeInit.java
public static final void setApplicationObject(IBinder app) {
mApplicationObject = app;
}
private static IBinder mApplicationObject;
final ApplicationThread mAppThread = new ApplicationThread();//ActivityThread有一个ApplicationThread类型的成员mAppThread
private class ApplicationThread extends ApplicationThreadNative//ApplicationThread继承自ApplicationThreadNative
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread//ApplicationThreadNative继承自Binder并实现了IApplicationThread接口
public IBinder asBinder()
{
return this;
}
RuntimeInit.setApplicationObject(mAppThread.asBinder());是将mAppThread作为Binder保存在RuntimeInit中。
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton gDefault = new Singleton() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
public abstract class Singleton {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
public abstract class ActivityManagerNative extends Binder implements IActivityManager//ActivityManagerNative同样也是继承自Binder并实现了IActivityManager接口
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
private IInterface mOwner;
private String mDescriptor;
String descriptor = "android.app.IActivityManager";//这是IActivityManager中的descriptor的定义
ServiceManager.getService("activity")通过ServiceManager的getService方法返回了一个IBinder对象,然后通过它的queryLocalInterface方法返回一个IInterface对象并强转为IActivityManager,如果这个IActivityManager为null则new一个ActivityManagerProxy对象,并把代表ActivityManagerService的IBinder对象传给ActivityManagerProxy的构造方法。
class ActivityManagerProxy implements IActivityManager
{
public ActivityManagerProxy(IBinder remote)
{
mRemote = remote;
}
public IBinder asBinder()
{
return mRemote;
}
}
final IActivityManager mgr = ActivityManagerNative.getDefault();通过ServiceManager获取ActivityManagerService的IBinder对象,并Cast为IActivityManager。
下面我们看一下ServiceManager的代码。
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);//先从缓存中获取
if (service != null) {
return service;
} else {//如果缓存中没有
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
private static HashMap sCache = new HashMap();
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
private static IServiceManager sServiceManager;
public abstract class ServiceManagerNative extends Binder implements IServiceManager//ServiceManagerNative也是继承自Binder并实现了IServiceManager接口
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
//ServiceManagerNative与ActivityManagerNative类似
代表ActivityManagerService的IBinder对象是通过ServiceManager的get方法得到的,而代表'ServiceManagerService'的IBinder对象是通过BinderInternal.getContextObject()得到。
public static final native IBinder getContextObject();//这是一个native方法
关于Binder的分析暂时不继续深入,我们直接跨过IPC,看ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
/**
* Return the ID of the process that sent you the current transaction
* that is being processed. This pid can be used with higher-level
* system services to determine its identity and check permissions.
* If the current thread is not currently executing an incoming transaction,
* then its own pid is returned.
*/
public static final native int getCallingPid();
/**
* Reset the identity of the incoming IPC on the current thread. This can
* be useful if, while handling an incoming call, you will be calling
* on interfaces of other objects that may be local to your process and
* need to do permission checks on the calls coming into them (so they
* will check the permission of your own local process, and not whatever
* process originally called you).
*
* @return Returns an opaque token that can be used to restore the
* original calling identity by passing it to
* {@link #restoreCallingIdentity(long)}.
*
* @see #getCallingPid()
* @see #getCallingUid()
* @see #restoreCallingIdentity(long)
*/
public static final native long clearCallingIdentity();
* Restore the identity of the incoming IPC on the current thread
* back to a previously identity that was returned by {@link
* #clearCallingIdentity}.
*
* @param token The opaque token that was previously returned by
* {@link #clearCallingIdentity}.
*
* @see #clearCallingIdentity
*/
public static final native void restoreCallingIdentity(long token);
//在clearCallingIdentity和restoreCallingIdentity之间如果检查权限,将会检查这个Servie进程的权限,而不会检查调用进程的权限。(不知道这样理解对不对)
attachApplicationLocked(thread, callingPid);非常复杂,暂时不管。
回到ActivityThread的main方法。
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
final Handler getHandler() {
return mH;
}
final H mH = new H();
private class H extends Handler;
static volatile Handler sMainThreadHandler;
然后调用Looper.loop();
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 (;;) {//这里是一个死循环
Message msg = queue.next(); // might block,从MessageQueue中获取Message
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
try {
msg.target.dispatchMessage(msg);//msg.target就是一个Handler
} finally {
}
msg.recycleUnchecked();//放入消息池回收
}
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);//如果Message带有一个Callback,实际是一个Runnable,则直接执行它的run方法。
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//子类复写这个方法并处理自己的业务逻辑
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
Handler的sendMessage方法最终会调用enqueueMessage
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//将Message与Handler关联
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);//调用MessageQueue的enqueueMessage方法
}
MessageQueue简单来说就是一个消息队列,队列有先进先出的特性,它通过enqueueMessage方法来使消息入队,在Looper的loop循环中通过next方法获取队头的消息。消息队列的入队和出队比较复杂,暂时不做分析。
最后给出Handler的典型用法
private static class MyHandler extends Handler {
private final WeakReference mOuter;
public MyHandler(OuterActivity outer) {
mOuter = new WeakReference(outer);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
OuterActivity outer = mOuter.get();
if (outer != null) {
switch (msg.what) {
//业务逻辑
}
}
}
}