Handler

作者: SimplerWorld | 来源:发表于2017-12-12 16:02 被阅读0次

    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<Looper> sThreadLocal = new ThreadLocal<Looper>();
    

    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<ThreadLocal<?>> {
                /** 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<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
                IBinder b = ServiceManager.getService("activity");
                IActivityManager am = asInterface(b);
                return am;
            }
        };
    
    public abstract class Singleton<T> {
        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<String, IBinder> sCache = new HashMap<String, IBinder>();
    
        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<OuterActivity> mOuter;
    
            public MyHandler(OuterActivity outer) {
                mOuter = new WeakReference<OuterActivity>(outer);
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                OuterActivity outer = mOuter.get();
                if (outer != null) {
                    switch (msg.what) {
                       //业务逻辑
                    }
                }
            }
        }
    

    相关文章

      网友评论

          本文标题:Handler

          本文链接:https://www.haomeiwen.com/subject/fexnixtx.html