Android 主線程之旅——PSVM(public static void main)

jopen 9年前發布 | 30K 次閱讀 Android Android開發 移動開發

原文出處: Square官方技術博客   譯文出處: Android Cool Posts   

當碰到與Android主線程交互相關的Bug時,我決定好好去看看Android的主線程究竟是怎么一回事。這篇文章就是描述我的Android主線程之旅的第一部分。

PSVM

public class BigBang {
  public static void main(String... args) {
    // The Java universe starts here.
  }
}

眾所周知,所有的Java程序的入口都是public static void main()方法。這對所有的Java 桌面程序、J2EE以及Android程序都是成立的。

當Android啟動時,它會開啟一個叫做ZygoteInit的Linux進程。這個進程是一個Dalvik 虛擬機,它會在一個線程上面加載Android SDK里面大部分的常用類,然后等待。

當Android啟動一個新的Android程序時,Android系統會fork這個ZygoteInit進程。接著子進程里面的線程會停止等待,然后調用ActivityThread.main()方法。

 Android 主線程之旅——PSVM(public static void main)

Wikipedia上面的一個Zygote。根據Wikipedia的定義,一個 Zygote 就是一個受精卵細胞。

Loopers

在繼續深入之前,我們需要來看一看Looper這個類。

使用looper可以連續地為一個線程處理它的消息。

每一個looper都有一個消息隊列(一個MessageQueue)。

每一個looper都有一個處理消息隊列里面所有消息的loop()方法,這個方法會在消息隊列為空時阻塞。

Looper.loop() 方法里面的代碼類似這樣:

public class BigBang {
  public static void main(String... args) {
    // The Java universe starts here.
  }
}

每一個looper都會和一個線程綁定。要創建一個新的looper并將它同當前的線程綁定起來,你必須要調用Looper.prepare()方法。這些looper都被存儲在Looper 類里面的靜態ThreadLocal變量里面。你可以通過調用Looper.myLooper()方法來獲取與當前線程相關聯的Looper。

當然實際情況不要這么復雜,其實HandlerThread類已經幫你做了所有事情:

public class BigBang {
  public static void main(String... args) {
    // The Java universe starts here.
  }
}

HandlerThread的內部代碼類似于這樣:

class HandlerThread extends Thread {
  Looper looper;
  public void run() {
    Looper.prepare(); // 創建一個Looper對象并將它保存到一個ThreadLocal 對象里面。
    looper = Looper.myLooper(); // 從ThreadLocal 里面獲取Looper以便后來的使用。
    Looper.loop(); // Loop forever.
  }
}

Handlers

handler 天生就是 looper 的好伙伴。

一個 handler 有兩個作用:

  • 從任意線程發送消息給一個looper的消息隊列;
  • 處理相關聯的looper發過來的消息。
class HandlerThread extends Thread {
  Looper looper;
  public void run() {
    Looper.prepare(); // 創建一個Looper對象并將它保存到一個ThreadLocal 對象里面。
    looper = Looper.myLooper(); // 從ThreadLocal 里面獲取Looper以便后來的使用。
    Looper.loop(); // Loop forever.
  }
}

你可以為一個looper關聯多個handler。looper會把message發送到message.target(它就是一個handler)這里。

一個常用簡單的用法就是使用handler來發送一個Runnable對象:

//創建包含一個runnable引用的message,然后將這個message添加到這個looper的消息隊列
handler.post(new Runnable() {
  public void run() {
    // 這會在與handler相關聯的looper對應的線程上運行
  }
});

一個handler也可以在沒有設置looper的情況下被創建。:

//創建包含一個runnable引用的message,然后將這個message添加到這個looper的消息隊列
handler.post(new Runnable() {
  public void run() {
    // 這會在與handler相關聯的looper對應的線程上運行
  }
});

handler的無參構造函數會調用方法來獲取與當前線程相關聯的looper。這個時候你要注意,可能當前線程不是你的handler想關聯的線程。

大部分時間,你只需要創建一個在主線程上面發送消息的handler就行了:

//創建包含一個runnable引用的message,然后將這個message添加到這個looper的消息隊列
handler.post(new Runnable() {
  public void run() {
    // 這會在與handler相關聯的looper對應的線程上運行
  }
});

Back to PSVM

讓我們再來看看ActivityThread.main()這個方法。下面就是這個方法的一些內部實現:

//創建包含一個runnable引用的message,然后將這個message添加到這個looper的消息隊列
handler.post(new Runnable() {
  public void run() {
    // 這會在與handler相關聯的looper對應的線程上運行
  }
});

現在你知道為什么這個線程被稱為主線程了吧:) .

注意: 主線程最先做的幾件事情之一就是創建Application對象,然后調用Application.onCreate()方法。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!