0%

Android 的消息机制(三):主线程的消息循环

1. 主线程消息循环概述

  • Android 的主线程就是运行 ActivityThread 的线程(由 Zygote fork 出来的进程)主线程的入口方法为 main() 方法

  • main() 方法中系统会通过 Looper.prepareMainLooper() 方法来创建主线程的 Looper 以及 MesssageQueue,并通过 Looper.loop() 方法来开启主线程的消息循环main() 方法源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // ActivityThread.java
    public static void main(String[] args) {
    // bla bla bla
    Looper.prepareMainLooper();

    // bla bla bla
    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.loop(); // 主线程开启消息轮询

    throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    1
    2
    3
    4
    5
    6
    // AcrivityThread.java
    final H mH = new H();
    @UnsupportedAppUsage
    final Handler getHandler() {
    return mH;
    }
  • 主线程的消息循环开始了以后,ActivityThread 还需要一个 Handler 来和消息队列进行交互,这个 Handler 就是其内部类 ActivityThread.H,它内部定义了一组消息类型,主要包含了四大组件的启动和停止等过程。类 H 源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    private class H extends Handler {
    // bla bla bla

    public static final int LAUNCH_ACTIVITY = 100;
    public static final int PAUSE_ACTIVITY = 101;
    public static final int PAUSE_ACTIVITY_FINISHING = 102;
    public static final int STOP_ACTIVITY_SHOW = 103;
    public static final int STOP_ACTIVITY_HIDE = 104;
    public static final int SHOW_WINDOW = 105;
    public static final int HIDE_WINDOW = 106;
    public static final int RESUME_ACTIVITY = 107;
    public static final int SEND_RESULT = 108;
    public static final int DESTROY_ACTIVITY = 109;
    public static final int BIND_APPLICATION = 110;
    public static final int EXIT_APPLICATION = 111;
    public static final int NEW_INTENT = 112;
    public static final int RECEIVER = 113;
    public static final int CREATE_SERVICE = 114;
    public static final int SERVICE_ARGS = 115;
    public static final int STOP_SERVICE = 116;

    // bla bla bla

    public void handleMessage(Message msg) {
    if (DEBUG_MESSAGE) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
    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;
    case EXIT_APPLICATION:
    if (mInitialApplication != null) {
    mInitialApplication.onTerminate();
    }
    Looer.myLooper().quit();
    break;
    case RECEIVER:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiverCom");
    handleReceiver((ReceiverData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
    case CREATE_SERVICE:
    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 STOP_SERVICE:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
    handleStopService((IBinder)msg.obj);
    schedulePurgeIdler();
    Trace.traceEnd(Trace。TRACE_TAG_ACTIVITY_MANAGER);
    break;
    ...
    case APPLICATION_INFO_CHANGED:
    mUpdatingSystemConfig = true;
    try {
    handleApplicationInfoChanged((Application)msg.obj);
    } finally {
    mUpdatingSystemConfig = false;
    }
    break;
    case RUN_ISOLATED_ENTRY_POINT:
    handleRunIsolatedEntryPoint((String) ((SomeArgs)msg.obj).arg1), (String[])((SomeArgs)msg.obj).arg2);
    break;
    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(lifecycle): Recycle locally scheduled transactions.
    break;
    case RELAUNCH_ACTIVITY:
    handleRelaunchActivityLocally((IBinder)msg.obj);
    break;
    case PURGE_RESOURCES:
    schedulePurgeIdler();
    break;
    }
    Object obj = msg.obj;
    if (obj instanceof SomeArgs) {
    ((SomeArgs)obj).recycle;
    }
    if (DEBUG_MESSAGE) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
    }
    }
    • ActivityThread 通过 ApplicationThreadAMS 进行 IPC 进程间通信
    • AMS 以进程间通信的方式完成 ActivityThread 的请求后会回调 ApplicationThread 中的 Binder 方法
    • 然后 ApplicationThread 会向 H 发送消息,H 收到消息后会将 ApplicationThread 中的逻辑切换到 ActivityThread 中去执行,即切换到主线程中去执行
    • Activity 的生命周期都是依靠主线程的 Looper.loop(),这个过程就是主线程的消息循环模型
    • 主线程 Looper 的退出机制
      • 在 App 退出时,ActivityThread 中的 mH(Handler)收到消息:case EXIT_APPLICATION:,执行退出操作:Looper.myLooper().quit();
      • 如果手动退出主线程 Looper,最终 MessageQueue 的 quit() 方法会抛出异常:throw new IllegalStateException("Main thread not allowed to quit.");
      • 正常情况下,主线程不允许退出,一旦退出就意味着程序挂了,即使退出也不应该用手动调主线程 Looper 的 quit() 方法的方式
-------------------- 本文结束感谢您的阅读 --------------------