Activity 与 Main Looper

上文抛出了一个疑问:UI 线程是在哪里绑定 Looper 呢?欲解此题,仍旧从 Android 源码着手,但是 Android 的代码量是以 GB 为单位来计算的,若是一个一个来看,只见树木不见森林,未必能理出个头绪。

不妨通过 Eclipse 这一工具,设置 breakpoint,进入 debug,看一看执行流程。新建一 Android Project,创建简单的 Activity 类,在 onCreate 方法中设置断点,应用进入 debug,在断点处暂停。

以下是通过 Eclipse Debug 看到的信息:

Eclipse Debug

Eclipse Debug

从上图可以看到各个相关类的调用流程,美中不足的是缺少类的 package 信息,庆幸的是, DDMS 给出了一个更趋完美的结果,如下图:

Eclipse DDMS

Eclipse DDMS

自下向上看起,来龙去脉一目了然。结合当前问题,暂时不理会“干扰”因素,直接进入 android.app.ActivityThread,– 不必从 Reference 中查找,因为该类已经被 hidden,直接看源码,以下即为 main 方法的源码:

public static final void main(String[] args) {
    Process.setArgV0("<pre-initialized>");
 
    Looper.prepareMainLooper();
 
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
 
    Looper.loop();
 
    // 以下内容省略
}

main 方法平淡无奇,和通常所见的 Java 程序一样,是一个入口。言归正题,Looper.prepareMainLooper() 是问题的切入点,那么究竟它做了什么呢?我们从文档注释中可以了解一二。

Initialize the current thread as a looper, marking it as an application’s main looper. The main looper for your application is created by the Android environment, so you should never need to call this function yourself.

注释如实反映了该方法的源码,首先调用 prepare(),为当前线程初始化 looper,而后调用 setMainLooper(),将这个 looper 设置成应用的 main looper。

public static final void prepareMainLooper() {
    prepare();
    setMainLooper(myLooper());
    if (Process.supportsProcesses()) {
        myLooper().mQueue.mQuitAllowed = false;
    }
}
 
public static final void prepare() {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());
}
 
private synchronized static void setMainLooper(Looper looper) {
    mMainLooper = looper;
}

此时,之前的疑问也就得到了解答。现在回过头,再来看所谓的“UI 线程”,其实它就是主线程,而 ActivityThread 也并不是 Thread 的子类。

1 Comment

[…] ActivityThread 也并不是 Thread 的子类。 原文链接:http://www.poemcode.net/2010/03/activity-main-looper/ >>> 进入[Android2D游戏开发]主题文章列表 转载编辑: Fgamers […]

Leave a comment

Your comment