a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 系統 > Android > 正文

Android中檢測當前是否為主線程最可靠的解決方法

2020-04-11 11:41:18
字體:
來源:轉載
供稿:網友

如果在Android中判斷某個線程是否是主線程?對于這個問題,你可能說根據線程的名字,當然這個可以解決問題,但是這樣是最可靠的么?萬一某天Google一下子將線程的名字改稱其他神馬東西呢。

方法揭曉

下面的方法是最可靠的解決方案。

復制代碼 代碼如下:

public static boolean isInMainThread() {
      return Looper.myLooper() == Looper.getMainLooper();
}

實際上,寫到這里就基本解決了文章標題的問題了,但是僅僅研究到這里太膚淺了,刨的不夠深,所以需要繼續,希望你也可以繼續讀下去。

刨根問底

實驗一

好,現在,我們對這個穩定的方法做一些測試,首先,下面的方法會增加一些調試打印信息。

復制代碼 代碼如下:

private boolean isInMainThread() {
    Looper myLooper = Looper.myLooper();
  Looper mainLooper = Looper.getMainLooper();
  Log.i(LOGTAG, "isInMainThread myLooper=" + myLooper
      + ";mainLooper=" + mainLooper);
  return myLooper == mainLooper;
}

好,然后我們在主線程中運行一個測試,調用上述方法。比如我們這樣調用。

復制代碼 代碼如下:

Log.i(LOGTAG, "testInMainThread inMainThread=" + isInMainThread());

OK,我們看一下輸出日志。驗證OK。

復制代碼 代碼如下:

I/TestInMainThread(32028): isInMainThread myLooper=Looper{40d35ef8};mainLooper=Looper{40d35ef8}
I/TestInMainThread(32028): testInMainThread inMainThread=true

實驗二

現在我們繼續在一個沒有消息循環的非主線程,進行驗證。

復制代碼 代碼如下:

new Thread() {
    @Override
    public void run() {
      Log.i(LOGTAG, "testIn NOT in MainThread isMainThread="
          + isInMainThread());
      super.run();
  }
}.start();

正如我們看到的如下日志結果,主線程的Looper(翻譯成循環泵,不是很好聽)已經被初始化賦值。但是我們新創建的線程的looper還是null。這是因為Android中的線程默認沒有一個和它綁定了的消息循環(Threads by default do not have a message loop associated with them. Of course, the method works)

復制代碼 代碼如下:

I/TestInMainThread(32028): isInMainThread myLooper=null;mainLooper=Looper{40d35ef8}
I/TestInMainThread(32028): testIn NOT in MainThread isMainThread=false

實驗三

繼續,我們創建一個綁定了消息循環的線程,根據Android開發者文檔說明,以下是一個典型的創建消息循環線程的示例,使用單獨prepare()方法和loop()方法來創建一個綁定到Looper的Handler。

復制代碼 代碼如下:

new Thread() {
  private Handler mHandler;
  @Override
  public void run() {
      Looper.prepare();
      mHandler = new Handler() {
            public void handleMessage(Message msg) {
              // process incoming messages here
          }
      };
      Log.i(LOGTAG, "testInNonMainLooperThread isMainThread="
            + isInMainThread());
      Looper.loop();
  }
     
}.start();

OK,現在再次檢查以下日志,

復制代碼 代碼如下:

I/TestInMainThread(32028): isInMainThread myLooper=Looper{40d72c58};mainLooper=Looper{40d35ef8}
I/TestInMainThread(32028): testInNonMainLooperThread isMainThread=false

兩個Looper都被初始化賦值了,但是他們是不同的對象。

原理發掘

但是,這是為什么呢,這里面有什么奧秘呢? 好,讓我們看以下Looper.class

復制代碼 代碼如下:

// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;  // guarded by Looper.class

/**
 * 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.  See also: {@link #prepare()}
 */
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

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

/**
 * Return the Looper object associated with the current thread. 
 * Returns null if the calling thread is not associated with a Looper.
 */
public static Looper myLooper() {
    return sThreadLocal.get();
}

 /** Returns the application's main looper, which lives in the main thread of the application.
 */
public static Looper getMainLooper() {
    synchronized (Looper.class) {
        return sMainLooper;
    }
}

對于主線程來說,prepareMainLooper這個方法會被Android運行環境調用,而不是程序顯式調用。通過這個方法,主線程的looper被創建,并且將對象引用傳遞給sMainLooper。所以保證了主線程myLooper()獲取到的引用和getMainLooper()獲取到的都是同一個引用。

對于沒有消息循環的非主線程,默認的當前線程的looper是null,因為你從來沒有手動地調用prepare(),所以它和主線程的looper不一樣。

對于綁定了消息循環的非主線程,當調用Looper.prepare方法時,主線程的Looper已經由Android運行環境創建,當調用prepare方法后,綁定到這個非主線程的looper被創建,當然,這不可能和主線程的Looper一樣。

綜上所述,這個方法是可靠的。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄色影视 | 国产亚洲女人久久久久毛片 | 日本超碰在线 | 99精品国产高清一区二区麻豆 | 欧美日韩一 | 亚洲视频一区二区三区 | 成人免费在线视频 | 午夜在线播放 | 国产美女高潮一区二区三区 | 成人区精品一区二区婷婷 | 亚洲美女网址 | 国产ts人妖另类 | 欧美一区二区三区黄色 | 欧美视频一区二区三区在线观看 | 成人一区av | 成人在线不卡视频 | 欧美日韩国产高清 | 一区二区在线看 | 欧美一区二区三区在线视频 | 亚洲成人二区 | 成人欧美 | 极品少妇一区二区三区精品视频 | av自拍 | 秋霞毛片| 日韩三级网| 国产福利在线播放麻豆 | av在线不卡播放 | www.久久久久| 国产99久久| 欧美日韩视频在线第一区 | 欧美午夜影院 | 亚洲福利片 | 免费视频爱爱太爽了 | 91精品国产91综合久久蜜臀 | 91精品一区二区三区在线观看 | 亚州视频在线 | 日本成人一区二区 | 黄色一级毛片在线观看 | 免费观看成人性生生活片 | 日本天堂在线播放 | 国产又粗又长又硬又猛电影 |