Handler

一些面试问题:

  • 1.一个线程有几个Handler?
  • 2.一个线程有几个looper,如何保证的?
  • 3.Handler内存泄漏原因?为什么其他的内部类没有说过这个问题?
  • 4.为何主线程可以new Handler?如果想要在子线程中new handler要做什么准备
  • 5.子线程中维护的Looper,消息队列无消息的时候处理方案是什么?有什么用?
  • 6.既然可以存在多个Handler往MessageQueue中添加数据(发消息时各个Handler可能处于不同线程),那它内部是如何保证线程安全的?
  • 7.我们使用Message时应该如何创建它?
  • 8.Looper死循环为什么不会导致应用卡死?

首先了解Handle是用于线程间通讯的,是整个App中的通信框架。

最常用的sendMessage的流程
handle.sendMessage() ->messageQueue.enqueueMessage
looper.loop()->messageQueue.next()->handler.dispatchMessage()->handle.handleMessage()
其中会涉及到类包括MessageQueue和Looper。

1.Android启动主线程中的Handler

Handle发送消息到MessageQueue中,然后Looper进行一个死循环来从MessageQueue中取消息,特别是我们在子线程中使用Handle时,我们要自己去启动Looper,不然Handle根本不起作用。但是在Android的主线程中我们并没有手动去启动looper,那么它是怎么来的?
来看一下Android程序的主入口,ActivityThread.main()->

 public static void main(String[] args) {
        //省略部分代码
        //这里启动了Looper
        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        
        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中是一个轮询操作
        Looper.loop();
        //执行到这里说明主线程中的Looper意外退出了,那么程序也就挂掉了
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

Looper中相关的方法分析:

    /**
    构建主线程的Looper和MessageQueue
    */
    @Deprecated
    public static void prepareMainLooper() {
        //这里就是构建了一个不允许退出的Looper并放到了sThreadLocal(ThreadLocal)中
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            //主线程的Looper
            sMainLooper = myLooper();
        }
    }
    /**
    quitAllowed是否允许退出
    */
     private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

    /**
    looper的轮询操作
    */
    public static void loop() {
        //获取当前线程的Looper
        final Looper me = myLooper();
        //如果为空的话,说明Looper还没有创建
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        if (me.mInLoop) {
            Slog.w(TAG, "Loop again would have the queued messages be executed"
                    + " before this one completed.");
        }

        me.mInLoop = true;

        // 确保该线程的身份是本地进程的身份,并跟踪该身份令牌实际上是什么。
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        // 允许使用系统道具覆盖阈值。例如adb shell 'setprop log.looper.1000.main.slow 1 && 停止 && 开始'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        me.mSlowDeliveryDetected = false;

        for (;;) {
            //在当前Looper的MessageQueue中取Message
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }

2.主线程的Handler都处理了什么?

public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                //这个应该是初始化应用信息的,handleBindApplication中有设置应用的TargetVersion,时间格式(12或者24)等
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //处理应用退出,可以看到主线程的Looper调用了quit停止了
                case EXIT_APPLICATION:
                    if (mInitialApplication != null) {
                        mInitialApplication.onTerminate();
                    }
                    Looper.myLooper().quit();
                    break;
                    //这里应该是处理广播接受
                case RECEIVER:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
                    handleReceiver((ReceiverData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //创建服务
                case CREATE_SERVICE:
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                                ("serviceCreate: " + String.valueOf(msg.obj)));
                    }
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //绑定服务
                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //解绑服务
                case UNBIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
                    handleUnbindService((BindServiceData)msg.obj);
                    schedulePurgeIdler();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //应该是启动服务
                case SERVICE_ARGS:
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                                ("serviceStart: " + String.valueOf(msg.obj)));
                    }
                    handleServiceArgs((ServiceArgsData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //停止服务
                case STOP_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
                    handleStopService((IBinder)msg.obj);
                    schedulePurgeIdler();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //配置信息发生变化(主题等)
                case CONFIGURATION_CHANGED:
                    mConfigurationController.handleConfigurationChanged((Configuration) msg.obj);
                    break;
                    //移除上下文,看内部代码实现应该是注销广播的接受者和服务的Connection
                case CLEAN_UP_CONTEXT:
                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
                    cci.context.performFinalCleanup(cci.who, cci.what);
                    break;
                    //空闲时调用GC
                case GC_WHEN_IDLE:
                    scheduleGcIdler();
                    break;
                    //转储服务 -不清楚做什么
                case DUMP_SERVICE:
                    handleDumpService((DumpComponentInfo)msg.obj);
                    break;
                    //转储 GFXINFO -不清楚做什么
                case DUMP_GFXINFO:
                    handleDumpGfxInfo((DumpComponentInfo) msg.obj);
                    break;
                    //内存低
                case LOW_MEMORY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
                    handleLowMemory();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //传感器?
                case PROFILER_CONTROL:
                    handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
                    break;
                    //创建备份--应该就是activity中创建备份的地方
                case CREATE_BACKUP_AGENT:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //销毁备份
                case DESTROY_BACKUP_AGENT:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
                    handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //自杀,杀进程
                case SUICIDE:
                    Process.killProcess(Process.myPid());
                    break;
                    //移除内容提供者
                case REMOVE_PROVIDER:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
                    completeRemoveProvider((ProviderRefCount)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //分发广播
                case DISPATCH_PACKAGE_BROADCAST:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //抛出远程服务异常
                case SCHEDULE_CRASH:
                    throwRemoteServiceException((String) msg.obj, msg.arg1);
                    break;
                    //处理转储堆
                case DUMP_HEAP:
                    handleDumpHeap((DumpHeapData) msg.obj);
                    break;
                    //将 Activity 的状态打印到给定的流中。 如果您运行“adb shell dumpsys activity <activity_component_name>”,则会调用它。
                case DUMP_ACTIVITY:
                    handleDumpActivity((DumpComponentInfo)msg.obj);
                    break;
                    //将提供者的状态打印到给定的流中。 如果您运行“adb shell dumpsys activity provider <provider_component_name>”,则会调用此方法。
                case DUMP_PROVIDER:
                    handleDumpProvider((DumpComponentInfo)msg.obj);
                    break;
                    //核心设置(?)更改后,重启所有的Activity
                case SET_CORE_SETTINGS:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
                    handleSetCoreSettings((Bundle) msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //处理更新包兼容性信息
                case UPDATE_PACKAGE_COMPATIBILITY_INFO:
                    handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
                    break;
                    //内容提供者销毁时?
                case UNSTABLE_PROVIDER_DIED:
                    handleUnstableProviderDied((IBinder)msg.obj, false);
                    break;
                    //处理请求协助上下文附加
                case REQUEST_ASSIST_CONTEXT_EXTRAS:
                    handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
                    break;
                    //半透明转换完成
                case TRANSLUCENT_CONVERSION_COMPLETE:
                    handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
                    break;
                    //处理安装提供程序
                case INSTALL_PROVIDER:
                    handleInstallProvider((ProviderInfo) msg.obj);
                    break;
                    //一个新的Activity选项?
                case ON_NEW_ACTIVITY_OPTIONS:
                    Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
                    onNewActivityOptions(pair.first, pair.second);
                    break;
                    //进入动画完成
                case ENTER_ANIMATION_COMPLETE:
                    handleEnterAnimationComplete((IBinder) msg.obj);
                    break;
                    //启用 Binder IPC 跟踪。
                case START_BINDER_TRACKING:
                    handleStartBinderTracking();
                    break;
                    //应该就是停止Binder并销毁
                case STOP_BINDER_TRACKING_AND_DUMP:
                    handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
                    break;
                    //本地语音交互开始
                case LOCAL_VOICE_INTERACTION_STARTED:
                    handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
                            (IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
                    break;
                    //附加代理
                case ATTACH_AGENT: {
                    Application app = getApplication();
                    handleAttachAgent((String) msg.obj, app != null ? app.mLoadedApk : null);
                    break;
                }
                /**
                包安装触发的更新通过包更新接收器。在这里,我们尝试捕获由其他来源(例如覆盖)引起的 ApplicationInfo 更改。这意味着我们希望对代码更改尽可能保守。获取旧 ApplicationInfo 和新 ApplicationInfo 的差异,看看是否需要更改任何内容。
                */
                case APPLICATION_INFO_CHANGED:
                    handleApplicationInfoChanged((ApplicationInfo) msg.obj);
                    break;
                    //运行隔离入口点
                case RUN_ISOLATED_ENTRY_POINT:
                    handleRunIsolatedEntryPoint((String) ((SomeArgs) msg.obj).arg1,
                            (String[]) ((SomeArgs) msg.obj).arg2);
                    break;
                    //这里是12中对之前生命周期的一个统一入口,改为状态模式
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
                        // message is handled.
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;
                    //重新启动Activity,活动状态必须在 [ON_START..ON_STOP] 才能重新启动
                case RELAUNCH_ACTIVITY:
                    handleRelaunchActivityLocally((IBinder) msg.obj);
                    break;
                    //清除资源
                case PURGE_RESOURCES:
                    schedulePurgeIdler();
                    break;
                    //附加启动参数
                case ATTACH_STARTUP_AGENTS:
                    handleAttachStartupAgents((String) msg.obj);
                    break;
                    //更新UI状态
                case UPDATE_UI_TRANSLATION_STATE:
                    final SomeArgs args = (SomeArgs) msg.obj;
                    updateUiTranslationState((IBinder) args.arg1, (int) args.arg2,
                            (TranslationSpec) args.arg3, (TranslationSpec) args.arg4,
                            (List<AutofillId>) args.arg5, (UiTranslationSpec) args.arg6);
                    break;
                    //这里应该是对应内容提供者的,内容收集者
                case SET_CONTENT_CAPTURE_OPTIONS_CALLBACK:
                    handleSetContentCaptureOptionsCallback((String) msg.obj);
                    break;
                    /**
                    在检测启动时调用,在加载任何应用程序代码之前。 通常这将被实现为简单地调用start来start检测线程,然后在onStart继续执行。
如果您不需要自己的线程——也就是说,您正在编写完全异步的检测(返回到事件循环以便应用程序可以运行),您可以简单地在此处开始检测,例如调用Context.startActivity开始适当的应用程序的第一个活动。
                    */
                case INSTRUMENT_WITHOUT_RESTART:
                    handleInstrumentWithoutRestart((AppBindData) msg.obj);
                    break;
                    //销毁上面的检测对象
                case FINISH_INSTRUMENTATION_WITHOUT_RESTART:
                    handleFinishInstrumentationWithoutRestart();
                    break;
            }
            Object obj = msg.obj;
            if (obj instanceof SomeArgs) {
                ((SomeArgs) obj).recycle();
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
        }

可以看到和四大组件(Activity,Service,Broadcast,ContentProvider)相关的都有,还有应用信息的设置,启动和关闭应用,UI的更新

3.Handler的消息发送

最常使用的sendMessage:

 public final boolean sendMessage(@NonNull Message msg) {
        return sendMessageDelayed(msg, 0);
}

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
     if (delayMillis < 0) {
        delayMillis = 0;
    }
     return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

 public boolean sendMessageAtTime(@NonNull 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);
 }

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
    //消息这里也就和Handler进行的绑定,所以这里也就是为什么Handler会有内存溢出的问题
    //handler的处理一般都是作为内部类去使用,但是当handler持有外部类的引用时,而消息需要等待的时间比较长,
    //例如20分钟,但是当前的Activity已经退出要销毁,根据GC的可达性分析,Message持有Handler,
    //Handler又持有Activity的引用,所以这里GC就无法进行回收,从而发生异常。内存溢出很大的可能
    //都是因为生命周期不一致引起的。
    msg.target = this;
    msg.workSourceUid = ThreadLocalWorkSource.getUid();

    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    //见MessageQueue的方法分析
     return queue.enqueueMessage(msg, uptimeMillis);
}

MessageQueue相关方法分析:

boolean enqueueMessage(Message msg, long when) {
    //msg的target就是handler,如果没有那么这就没有消费者了
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        //加锁保证在同一时刻只有一个插入消息队列的操作,并且没有其他的操作(取消息和消息退出)
        synchronized (this) {
            if (msg.isInUse()) {
                throw new IllegalStateException(msg + " This message is already in use.");
            }
            //Looper退出时会调用MessageQueue的quit设置mQuitting为true
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            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 {
                // 插入队列中间。通常我们不必唤醒事件队列,除非队列的头部有一个barrier(同步屏障),并且该消息是队列中最早的异步消息。
                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;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            //在这里如果当前的Looper是需要唤醒的,这里会执行
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

到这里Message已经到放入到MessageQueue中了,那么又是如何把消息取出来的并回掉给Handler中的handleMessage(Message msg)方法的呢?

4.Handle.handleMessage()的回调

前面我们已经看到,Handler需要在必须在Looper的环境中

public static void loop() {
        final Looper me = myLooper();
        //判断是否还没有启动Looper
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //判断是否重复启动Looper
        if (me.mInLoop) {
            Slog.w(TAG, "Loop again would have the queued messages be executed"
                    + " before this one completed.");
        }

        me.mInLoop = true;

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

        // Allow overriding a threshold with a system prop. e.g.
        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        me.mSlowDeliveryDetected = false;
        //轮询获取MessageQueue中的message
        for (;;) {
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }

    private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {
        Message msg = me.mQueue.next(); // might block
        if (msg == null) {
            //没有消息表示消息队列正在退出。
            return false;
        }

        // This must be in a local variable, in case a UI event sets the logger
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " "
                    + msg.callback + ": " + msg.what);
        }
        // Make sure the observer won't change while processing a transaction.
        final Observer observer = sObserver;

        final long traceTag = me.mTraceTag;
        long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
        long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
        if (thresholdOverride > 0) {
            slowDispatchThresholdMs = thresholdOverride;
            slowDeliveryThresholdMs = thresholdOverride;
        }
        final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
        final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

        final boolean needStartTime = logSlowDelivery || logSlowDispatch;
        final boolean needEndTime = logSlowDispatch;

        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }

        final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
        final long dispatchEnd;
        Object token = null;
        if (observer != null) {
            token = observer.messageDispatchStarting();
        }
        long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
        try {
            //这里的target就是Handler,处理消息的分发
            msg.target.dispatchMessage(msg);
            if (observer != null) {
                observer.messageDispatched(token, msg);
            }
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        } catch (Exception exception) {
            if (observer != null) {
                observer.dispatchingThrewException(token, msg, exception);
            }
            throw exception;
        } finally {
            ThreadLocalWorkSource.restore(origWorkSource);
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        if (logSlowDelivery) {
            if (me.mSlowDeliveryDetected) {
                if ((dispatchStart - msg.when) <= 10) {
                    Slog.w(TAG, "Drained");
                    me.mSlowDeliveryDetected = false;
                }
            } else {
                if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                        msg)) {
                    // Once we write a slow delivery log, suppress until the queue drains.
                    me.mSlowDeliveryDetected = true;
                }
            }
        }
        if (logSlowDispatch) {
            showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
        }

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

        return true;
    }

这里我们首先要看一下MessageQueue中的next怎么获取消息的

Message next() {
        //如果消息循环已经退出并被处理,则返回此处。如果应用程序在退出后尝试重新启动不受支持的 Looper,就会发生这种情况。
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                //查找同步屏障的消息
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        //下一条消息未准备好。设置超时以在准备好时唤醒。
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        //这里返回当前需要处理的消息
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }

                //现在处理退出消息,所有挂起的消息都已处理完毕。
                if (mQuitting) {
                    dispose();
                    return null;
                }

                // 如果第一次空闲,则获取要运行的空闲程序的数量。空闲句柄仅在队列为空或队列中的第一条消息(可能是障碍)将在未来处理时运行。
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

在获取到消息之后,在Looper中的loopOnce方法里 msg.target.dispatchMessage(msg);,其中Message的Target就是Handler

  public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //handleMessage被调用了
            handleMessage(msg);
        }
    }

到这一步整个流程串起来了,但是有两个问题

  • 1.当消息队列没有消息的时候,Looper是处于什么样的状态,因为它是一个循环操作,会阻塞线程?
  • 2.当队列中第一个消息的触发时间还没到的话,又是怎么处理的?
    这个两个问题我们都可以从MessageQueue中的next()方法中找到答案:
 Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            //nextPollTimeoutMillis就是下一个任务需要等待执行的时间,如果nextPollTimeoutMillis为-1,那么这个Looper会一直休眠等待下去,所以子线程中的Looper没有消息要处理了要及时调用quite
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        //获取到的消息没有到执行的时间,获取一个执行时间差
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    //这里就是消息队列中没有消息了
                    nextPollTimeoutMillis = -1;
                }

                // 只有调用quite之后mQuitting才为true
                if (mQuitting) {
                    dispose();
                    return null;
                }

                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                //在这里跳到下一个循环,looper就开始等待了
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

到这里我们也就是可以知道为什么Handler能够把我们在子线程发的消息转换到主线程来了,handler线程间通信是通过共享内存实现的,内存是不分线程的,但是函数是有线程区分的,当我们在子线程通过handler.sendMessage(msg)-》MessageQueue.equeueMessage(msg)这个就是子线程操作并在MessageQueue管理的内存空间中写入一个对象数据
而在主线程中的Looper不断的轮询消息队列的方法loop是执行在主线程的,它不断的在主线程中从MessageQueue中拿消息,这样就完成了线程切换。

5.那么在Looper是如何保证在线程的唯一性?

ThreadLocal 可以进行线程数据隔离,每个线程都有单独的一个副本
每个线程都只会有一个Looper,它就是通过ThreadLocal来进行实现的

Looper相关的源码:

public final class Looper {
    //ThreadLocal只有有一个,并且Looper的构造方法私有化,那么只能通过prepare()方法来进行调用
   static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    /**
    将当前线程初始化为循环程序。 这使您有机会创建处理程序,然后在实际开始循环之前引用此循环程序。 调用此方法后一定要调用loop() ,并通过调用quit()结束它。
    */
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        //首先检查当前是否已经有Looper,有那么就抛出异常,从而保证了一个线程只有一个Looper
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

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

ThreadLocal:

/**
将此线程局部变量的当前线程副本设置为指定值。 大多数子类将不需要覆盖此方法,仅依赖于initialValue方法来设置线程initialValue的值。
参数:
value -- 要存储在此线程本地的当前线程副本中的值。
*/
    public void set(T value) {
        //获取当前线程
        Thread t = Thread.currentThread();
        //通过线程获取ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

6.同步屏障

在Android中Handler的同步屏障实现方式,是在需要的地方往消息队列中插入一条target为null的Message,根据前面的源码分析可以看到正常的消息的target就是要处理消息的Handler,在MessageQueue的next方法中,会判断当前消息。
同步屏障消息的触发:

/**
向循环程序的消息队列发送一个同步障碍。在消息队列遇到已发布的同步障碍之前,消息处理照常进行。
当遇到barrier时,队列中稍后的同步消息将被暂停(阻止执行),直到barrier通过调用removeSyncBarrier并指定标识同步barrier的令牌被释放。
此方法用于立即推迟所有随后发布的同步消息的执行,直到满足释放barrier的条件。
异步消息(请参见消息。isAsynchronous不受此障碍的限制,并照常进行处理。
该调用必须始终与removeSyncBarrier调用匹配,以确保消息队列恢复正常操作。
否则,应用程序可能会挂起! 
*/
 public int postSyncBarrier() {
        return postSyncBarrier(SystemClock.uptimeMillis());
    }

    private int postSyncBarrier(long when) {
        // 加入一个新的同步障碍令牌。
        //我们不需要唤醒队列,因为屏障的目的是让它停滞。
        synchronized (this) {
            final int token = mNextBarrierToken++;
            //创建一个target为null的Message
            final Message msg = Message.obtain();
            msg.markInUse();
            msg.when = when;
            msg.arg1 = token;

            Message prev = null;
            Message p = mMessages;
            if (when != 0) {
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
            }
            if (prev != null) { // invariant: p == prev.next
                msg.next = p;
                prev.next = msg;
            } else {
                msg.next = p;
                mMessages = msg;
            }
            return token;
        }
    }

同步屏障释放:

 public void removeSyncBarrier(int token) {
        //从队列中删除同步障碍令牌。
        //如果队列不再被障碍物阻碍,那么唤醒它。
        synchronized (this) {
            Message prev = null;
            Message p = mMessages;
            while (p != null && (p.target != null || p.arg1 != token)) {
                prev = p;
                p = p.next;
            }
            if (p == null) {
                throw new IllegalStateException("The specified message queue synchronization "
                        + " barrier token has not been posted or has already been removed.");
            }
            final boolean needWake;
            if (prev != null) {
                prev.next = p.next;
                needWake = false;
            } else {
                mMessages = p.next;
                needWake = mMessages == null || mMessages.target != null;
            }
            p.recycleUnchecked();

            //如果循环退出,那么它已经醒了。
            //当mquit为false时,我们可以假设mPtr != 0。
            if (needWake && !mQuitting) {
                nativeWake(mPtr);
            }
        }
    }

同步屏障在消息队列中的处理,当获取到同步屏障消息后这个消息会一直在,当下次循环的时候,我们获得还是同步屏障的消息,然后继续查找异步的消息进行处理,直到调用移除同步屏障消息:

//被障碍阻碍了。在队列中查找下一个异步消息。
 if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }

应用场景,最常见的就是屏幕刷新,屏幕刷新必然是要实时响应的,队列中这时候其他消息都要先被同步屏障挡掉,处理界面刷新的异步消息。
在ViewRootImpl中的scheduleTraversals()

    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            //先发送了同步屏障消息
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            //视图
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

   void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            //移除同步屏障
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
            //循环包括performMeasure,performLayout,performDraw
            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

7.面试问题回答

  • 1.一个线程有几个Handler?
    任意个,handler是new出来的
  • 2.一个线程有几个looper,如何保证的?
    只有一个,保障机制Looper的构建和ThreadLocal一起
  • 3.Handler内存泄漏原因?为什么其他的内部类没有说过这个问题?
    内存泄漏发送主要就是因为生命周期不一致的问题,Handler中容易持有外部类的引用,并且Message又会持有Handler,当Message没有回收时,根据可达性分析,这一系列的对象都无法被回收,也就发生内存泄漏了。
  • 4.为何主线程可以new Handler?如果想要在子线程中new handler要做什么准备
    在主线程中一创建就构建好了Looper了,但是子线程中没有,所有需要调用Looper.prepare()构建Looper,调用Looper.loop()启动Looper
  • 5.子线程中维护的Looper,消息队列无消息的时候处理方案是什么?有什么用?
    需要调用quit()方法来退出MessageQueue的循环,返回一个为null的Message
  • 6.既然可以存在多个Handler往MessageQueue中添加数据(发消息时各个Handler可能处于不同线程),那它内部是如何保证线程安全的?
    通过synchronized关键字包裹代码块实现,一个线程中只会有一个MessageQueue,所以在通过synchronized(this)加锁的代码(加入队列,取出,退出)的操作,同一时间只能由一个线程可以执行。
  • 7.我们使用Message时应该如何创建它?
    Message.obtain(),这是从消息的全量池中返回一个新的Message对象,避免分配新对象
  • 8.Looper死循环为什么不会导致应用卡死?
    其实这是两个概念的消息,整个应用的处理就是建立在Handler机制上的,所有的事件(点击,页面刷新等)都是通过消息机制完成的。
  • 9.MessageQueue队列处理机制,在fragment生命周期管理中的应用
    这个是要在事件场景去去看,例如Glide的依赖Fragment来提供对应生命周期的,在Glide中会提供一个SupportRequestMananagerFragment,一个无视图的Fragment用来安全存储RequestManager,可以用来启动、停止和管理针对Fragment或activity的目标发起的Glide请求。
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
      new HashMap<>();

  @NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
          //先通过FragmentManager查找对应tag的SupportRequestManagerFragment
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
        //在map中去查找对应的SupportRequestManagerFragment
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
          //都为说明没有创建过
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        //存入map中
        pendingSupportRequestManagerFragments.put(fm, current);
        //启动事物创建Fragment,内部通过handler发送消息
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //发送消息,这里的Handler创建的是主线程的Handler,和事物当中的在同一个线程中,那么
        //它们的消息队列是同一个,也就是当这个消息执行的时候,那么Fragment必然已经被创建完成了,
        //那么清除Map中的就没有问题了,避免了重复创建的问题。
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

    /**
    RequestManagerRetriever中的handleMessage
    */
  @Override
  public boolean handleMessage(Message message) {
    boolean handled = true;
    Object removed = null;
    Object key = null;
    switch (message.what) {
      case ID_REMOVE_FRAGMENT_MANAGER:
        android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
        key = fm;
        removed = pendingRequestManagerFragments.remove(fm);
        break;
      case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
        FragmentManager supportFm = (FragmentManager) message.obj;
        key = supportFm;
        //移除对应的Fragment
        removed = pendingSupportRequestManagerFragments.remove(supportFm);
        break;
      default:
        handled = false;
        break;
    }
    if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
      Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
    }
    return handled;
  }