最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android線程間通信Handler源碼詳解

 更新時間:2022年10月20日 14:28:18   作者:Quincy_Ye  
這篇文章主要為大家介紹了Android線程間通信Handler源碼示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

【Android】線程間通信 - Handler之使用篇主要講了 Handler 的創(chuàng)建,發(fā)送消息,處理消息 三個步驟。那么接下來,我們也按照這三個步驟,從源碼中去探析一下它們具體是如何實現(xiàn)的。本篇是關(guān)于創(chuàng)建源碼的分析。

01、 用法

先回顧一下,在主線程和非主線程是如何創(chuàng)建 Handler 的。

//主線程
private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
    override fun handleMessage(msg: Message) {
        when (msg.what) {
            1 -> {}
        }
    }
}
//子線程
Thread {
    Looper.prepare()
    val handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                1 -> {}
            }
        }
    }
    handler.sendEmptyMessage(1)
    Looper.loop()
}.start()

02、源碼

Handler 一共有 7 個構(gòu)造方法。但最后都會直接或間接使用到以下兩個構(gòu)造方法。所以我們看看兩個方法都做了什么事情吧。

//方法 1
//Handler.java
public Handler(@Nullable Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }
    mLooper = Looper.myLooper(); \\標識 1
    if (mLooper == null) { \\ 標識 3
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue; \\標識 2
    mCallback = callback;
    mAsynchronous = async;
}
//方法 2
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

方法 2 更加的簡單,那么我們就從它入手吧。在其中對 4 個變量進行賦值。分別是 mLooper, mQueue, mCallback, mAsynchronous。方法 1 主要也是對 4 個變量進行賦值。它們有什么作用,我們先不管,后面會講到。我們先來看看這方法 1 和方法 2 的區(qū)別是什么?

讓我們聚焦到標識 1 和標識 2,mLooper, mQueue 來源是通過 Looper 這個類中獲取的。那讓我們跟進去看看。

//跟進標識 1
//Looper.java
public static @Nullable Looper myLooper() {
   return sThreadLocal.get();
}

看到是通過 mThreadLocal.get() 獲得一個 Looper 實例。那么 mThreadLocal 的 Looper 又是哪里來的呢?讓我們找找 mThreadLocal.set() 方法,就知道了!

//Looper.java
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.prepare() 中添加的。

這里需要注意!

  • "Only one Looper may be created per thread",每個線程只能調(diào)用一次 prepare(),這也就意味著每個線程只有一個 Looper 。

可是看回在主線程中創(chuàng)建 Handler 的時候,我們并沒有調(diào)用 Looper.prepare() 方法。但是也正常運行了。那是為什么呢?那是因為在 ActivityThread 中的 main()已經(jīng)調(diào)用了。

//ActivityThread.java
public static void main(String[] args) {
    //...省略無關(guān)代碼
    Looper.prepareMainLooper(); \\標識 4
   //...
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
  //...
    Looper.loop();
}
//跟進標識 4
//Looper.java
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

這里需要注意!

  • 我們不僅不用調(diào)用,也不能調(diào)用。否則將會觸發(fā) IllegalStateException("The main Looper has already been prepared.") 異常。
  • 但是如果不是為主線程創(chuàng)建 Handler 的時候,我們就需要手動調(diào)用 Looper.prepare(), 否則該線程中的 Looper 為空,會觸發(fā)標識 3 的代碼塊。
  • 即會得到RuntimeException("Can't create handler inside thread " + Thread.currentThread()+ " that has not called Looper.prepare()")異常。

03、結(jié)語

圖源 |《第一行代碼》

最后結(jié)合《第一行代碼》中異步消息處理機制的流程圖。我們可以看出 Handler 創(chuàng)建過程主要是準備好了 Looper, MessageQueue 和 Handler 本身。

以上就是Android線程間通信Handler源碼詳解的詳細內(nèi)容,更多關(guān)于Android線程間通信Handler的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android利用CountDownTimer實現(xiàn)驗證碼倒計時效果實例

    Android利用CountDownTimer實現(xiàn)驗證碼倒計時效果實例

    這篇文章主要給大家介紹了關(guān)于Android如何利用CountDownTimer實現(xiàn)驗證碼倒計時效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-10-10
  • Android利用GridView實現(xiàn)單選效果

    Android利用GridView實現(xiàn)單選效果

    本篇文章主要介紹了Android利用GridView實現(xiàn)單選效果的相關(guān)知識,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-05-05
  • Android實現(xiàn)自定義加載框的代碼示例

    Android實現(xiàn)自定義加載框的代碼示例

    本篇文章主要介紹了Android實現(xiàn)自定義加載框的代碼示例,App在與服務器進行網(wǎng)絡交互的時候,有個提示加載框,有興趣的可以了解一下。
    2017-02-02
  • Flutter仿微信通訊錄實現(xiàn)自定義導航條的示例代碼

    Flutter仿微信通訊錄實現(xiàn)自定義導航條的示例代碼

    某些頁面比如我們在選擇聯(lián)系人或者某個城市的時候需要快速定位到我們需要的選項,一般都會需要像微信通訊錄右邊有一個導航條一樣的功能,本文將利用Flutter實現(xiàn)這一效果,需要的可以參考一下
    2022-04-04
  • React Native與Android 原生通信的方法

    React Native與Android 原生通信的方法

    本篇文章主要介紹了React Native與Android 原生通信的方法,主要是分享原生模塊與JS傳遞數(shù)據(jù)的幾種方式,非常具有實用價值,需要的朋友可以參考下
    2018-05-05
  • Android?Compose之Animatable動畫停止使用詳解

    Android?Compose之Animatable動畫停止使用詳解

    這篇文章主要為大家介紹了Android?Compose之Animatable動畫停止使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • Kotlin語言使用BroadcastReceiver示例介紹

    Kotlin語言使用BroadcastReceiver示例介紹

    Android開發(fā)的四大組件分別是:活動(activity),用于表現(xiàn)功能;服務(service),后臺運行服務,不提供界面呈現(xiàn);廣播接受者(Broadcast Receive),勇于接收廣播;內(nèi)容提供者(Content Provider),支持多個應用中存儲和讀取數(shù)據(jù),相當于數(shù)據(jù)庫,本篇著重介紹廣播組件
    2022-09-09
  • Android Http實現(xiàn)文件的上傳和下載

    Android Http實現(xiàn)文件的上傳和下載

    這篇文章主要為大家詳細介紹了Android Http實現(xiàn)文件的上傳和下載,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Android Studio 修改類的默認注釋圖文教程

    Android Studio 修改類的默認注釋圖文教程

    這篇文章主要介紹了Android Studio 修改類的默認注釋圖文教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android實現(xiàn)ListView異步加載的方法(改進版)

    Android實現(xiàn)ListView異步加載的方法(改進版)

    這篇文章主要介紹了Android實現(xiàn)ListView異步加載的方法,針對前面介紹的方法進行了線程操作的改進,具有一定參考借鑒價值,需要的朋友可以參考下
    2016-08-08

最新評論

娱乐| 景宁| 驻马店市| 宜章县| 康平县| 平遥县| 望谟县| 新乐市| 万宁市| 新民市| 离岛区| 淮阳县| 睢宁县| 琼海市| 潜山县| 拜泉县| 始兴县| 平顶山市| 方正县| 清镇市| 阜新市| 罗平县| 工布江达县| 大同县| 龙口市| 南昌市| 秦皇岛市| 青海省| 云南省| 井冈山市| 湛江市| 高阳县| 沙坪坝区| 丽江市| 镇江市| 鄯善县| 若尔盖县| 屯留县| 松滋市| 海兴县| 葵青区|