溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android中Handler、Thread、HandlerThread的區(qū)別有哪些

發(fā)布時(shí)間:2021-10-25 13:39:15 來(lái)源:億速云 閱讀:199 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹Android中Handler、Thread、HandlerThread的區(qū)別有哪些,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

一、前期知識(shí)儲(chǔ)備

(1)Handler類,上官方文檔,Handler

public class Handler.A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

(2)Thread類,上官方文檔,Thread

public class Thread. extends Object implements Runnable.A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.

Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority. Each thread may or may not also be marked as a daemon. When code running in some thread creates a new Thread object, the new thread has its priority initially set equal to the priority of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.

(3)HandlerThread類,上官方文檔,HandlerThread

public class HandlerThread. extends Thread. Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

二、三者的區(qū)別

①Handler:在android中負(fù)責(zé)發(fā)送和處理消息,通過(guò)它可以實(shí)現(xiàn)其他支線線程與主線程之間的消息通訊。

②Thread:Java進(jìn)程中執(zhí)行運(yùn)算的最小單位,亦即執(zhí)行處理機(jī)調(diào)度的基本單位。某一進(jìn)程中一路單獨(dú)運(yùn)行的程序。

③HandlerThread:一個(gè)繼承自Thread的類HandlerThread,Android中沒(méi)有對(duì)Java中的Thread進(jìn)行任何封裝,而是提供了一個(gè)繼承自Thread的類HandlerThread類,這個(gè)類對(duì)Java的Thread做了很多便利的封裝。

———————————————————我是分割線—————————————————————

其實(shí)這個(gè)問(wèn)題,最主要的關(guān)注點(diǎn)還是落在了HandlerThread類上,那么這個(gè)類到底有什么作用,所謂的便利封裝又體現(xiàn)在哪里?

觀察HandlerThread的官方文檔的兩句:①Thread. Handy class for starting a new thread that has a looper.②The looper can then be used to create handler classes.

釋義:HandlerThread對(duì)象start后可以獲得其Looper對(duì)象,并且使用這個(gè)Looper對(duì)象實(shí)例Handler,之后Handler就可以運(yùn)行在其他線程中了。

———————————————————我是分割線—————————————————————

那么Handler和Looper到底是什么關(guān)系,為什么HandlerThread要做這樣的處理?觀看下圖:

                      Android中Handler、Thread、HandlerThread的區(qū)別有哪些

Andriod提供了 Handler  和  Looper  來(lái)滿足線程間的通信。 Handler 先進(jìn)先出原則。 Looper 類用來(lái)管理特定線程內(nèi)對(duì)象之間的消息交換 (MessageExchange) 。 

1)Looper:  一個(gè)線程可以產(chǎn)生一個(gè) Looper 對(duì)象,由它來(lái)管理此線程里的 MessageQueue( 消息隊(duì)列 ) 和對(duì)消息進(jìn)行循環(huán)。 

2)Handler:  你可以構(gòu)造 Handler 對(duì)象來(lái)與 Looper 溝通,以便 push 新消息到 MessageQueue 里 ; 或者接收 Looper 從 Message Queue 取出 所送來(lái)的消息。 

3) Message Queue( 消息隊(duì)列 ): 用來(lái)存放線程放入的消息。 

4) Message:是線程間通訊的消息載體。兩個(gè)碼頭之間運(yùn)輸貨物,Message充當(dāng)集裝箱的功能,里面可以存放任何你想傳遞的消息。

看到這里就明白了為什么:如果一個(gè)線程要處理消息,那么它必須擁有自己的Looper,并不是Handler在哪里創(chuàng)建,就可以在哪里處理消息。

注:對(duì)應(yīng)關(guān)系Thread(1):Looper(1):MessageQueen(1):Handler(n).

三、HandlerThread的使用

正如前面所說(shuō),線程間通信的時(shí)候,比如Android中常見(jiàn)的更新UI,涉及到的是子線程和主線程之間的通信,實(shí)現(xiàn)方式就是Handler+Looper,但是要自己手動(dòng)操作Looper,不推薦,所以谷歌封裝了HandlerThread類(類似于AsyncTask類)。

上代碼,具體實(shí)現(xiàn):

public class MainActivity extends AppCompatActivity {
 
    Handler mainHandler,workHandler;
    HandlerThread mHandlerThread;
    TextView text;
    Button button1,button2;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView) findViewById(R.id.text1);
 
        // 創(chuàng)建與主線程關(guān)聯(lián)的Handler
        mainHandler = new Handler();
        /**
          * 步驟①:創(chuàng)建HandlerThread實(shí)例對(duì)象
          * 傳入?yún)?shù) = 線程名字,作用 = 標(biāo)記該線程
          */
        mHandlerThread = new HandlerThread("handlerThread");
 
        /**
         * 步驟②:?jiǎn)?dòng)線程
         */
        mHandlerThread.start();
 
        /**
         * 步驟③:創(chuàng)建工作線程Handler & 復(fù)寫handleMessage()
         * 作用:關(guān)聯(lián)HandlerThread的Looper對(duì)象、實(shí)現(xiàn)消息處理操作 & 與其他線程進(jìn)行通信
         * 注:消息處理操作(HandlerMessage())的執(zhí)行線程 = mHandlerThread所創(chuàng)建的工作線程中執(zhí)行
         */
 
        workHandler = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg)
            {
                //設(shè)置了兩種消息處理操作,通過(guò)msg來(lái)進(jìn)行識(shí)別
                switch(msg.what){
                    case 1:
                        try {
                            //延時(shí)操作
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 通過(guò)主線程Handler.post方法進(jìn)行在主線程的UI更新操作
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run () {
                                text.setText("第一次執(zhí)行");
                            }
                        });
                        break;
                    case 2:
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run () {
                                text.setText("第二次執(zhí)行");
                            }
                        });
                        break;
                    default:
                        break;
                }
            }
        };
 
        /**
         * 步驟④:使用工作線程Handler向工作線程的消息隊(duì)列發(fā)送消息
         * 在工作線程中,當(dāng)消息循環(huán)時(shí)取出對(duì)應(yīng)消息 & 在工作線程執(zhí)行相關(guān)操作
         */
        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = Message.obtain();
                msg.what = 1; //消息的標(biāo)識(shí)
                msg.obj = "A"; // 消息的存放
                // 通過(guò)Handler發(fā)送消息到其綁定的消息隊(duì)列
                workHandler.sendMessage(msg);
            }
        });
 
        button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = Message.obtain();
                msg.what = 2; 
                msg.obj = "B"; 
                workHandler.sendMessage(msg);
            }
        });
 
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandlerThread.quit(); // 退出消息循環(huán)
        workHandler.removeCallbacks(null); // 防止Handler內(nèi)存泄露 清空消息隊(duì)列
    }
}

從上面代碼可以看出,HandlerThread繼承于Thread,所以它本質(zhì)就是個(gè)Thread。與普通Thread的差別就在于,然后在內(nèi)部直接實(shí)現(xiàn)了Looper的實(shí)現(xiàn),這是Handler消息機(jī)制必不可少的。有了自己的looper,可以讓我們?cè)谧约旱木€程中分發(fā)和處理消息。如果不用HandlerThread的話,需要手動(dòng)去調(diào)用Looper.prepare()Looper.loop()這些方法。

// 子線程中創(chuàng)建新的Handler 沒(méi)有使用HandlerThread
new Thread () {
    @Override
    public void run() {
        Looper.prepare();
        Hnadler handler = new Handler();
        Looper.loop();
    } 
}

提供一些其他Android消息機(jī)制分析,幫助理解讀者理解:

Android中Handler、Thread、HandlerThread的區(qū)別有哪些

①Handler是Android消息機(jī)制的上層接口,通過(guò)它可以輕松地將一個(gè)任務(wù)切換到Handler所在的線程中去執(zhí)行,該線程既可以是主線程,也可以是子線程,要看構(gòu)造Handler時(shí)使用的構(gòu)造方法中傳入的Looper位于哪里;

②Handler的運(yùn)行需要底層的MessageQueue和Looper的支撐,Handler創(chuàng)建的時(shí)候會(huì)采用當(dāng)前線程的Looper來(lái)構(gòu)造消息循環(huán)系統(tǒng),而線程默認(rèn)是沒(méi)有Looper的,如果需要使用Handler就必須為線程創(chuàng)建Looper;

③上述代碼中的第一個(gè)Handler-mainHandler,實(shí)例化的時(shí)候,直接在onCreate()方法中new出了實(shí)例,其實(shí)是其已經(jīng)在主線程中了,主線程-ActivityThread,ActivityThread被創(chuàng)建時(shí)就會(huì)初始化Looper,這就是主線程中默認(rèn)可以直接使用Handler的原因;

④上述代碼中的第二個(gè)Handler-workHandler,它在實(shí)例化的時(shí)候,參數(shù)傳入了 mHandlerThread.getLooper() ,注意,這個(gè)Handler使用的就不是主線程的Looper了,而是子線程的Looper,HandlerThread在調(diào)用start()方法之后,就可以獲取到子線程的Looper,然后將其傳入workHandler的構(gòu)造方法中,那么此時(shí)的workHandler就會(huì)運(yùn)行在子線程中,用于處理耗時(shí)操作。

⑤Handler的工作原理:Handler創(chuàng)建時(shí)會(huì)采用當(dāng)前線程的Looper來(lái)構(gòu)建內(nèi)部消息循環(huán)系統(tǒng),如果當(dāng)前線程沒(méi)有Looper,那么就會(huì)報(bào)錯(cuò)“Can`t create handler inside thread that has not called Looper.prepare()”解決方法有兩個(gè):為當(dāng)前線程創(chuàng)建Looper即可,像上述代碼中workHandler,或者在一個(gè)有Looper的線程中創(chuàng)建Handler也行,就像上述代碼中的mainHandler一樣;

⑥調(diào)用Handler的post方法會(huì)將一個(gè)Runnable投遞到Handler內(nèi)部的Looper中去處理,也可以通過(guò)Handler的send方法來(lái)發(fā)送一個(gè)消息,這個(gè)消息同樣會(huì)在Looper中去處理。其實(shí)post方法最終也是通過(guò)send方法來(lái)完成的。每當(dāng)Looper發(fā)現(xiàn)有新消息到來(lái)時(shí),就會(huì)處理這個(gè)消息,最終消息中的Runnable的run方法或者Handler的handleMessage方法就會(huì)被調(diào)用。注意Looper是運(yùn)行在創(chuàng)建Handler所在的線程中的,這樣一來(lái)Handler中的業(yè)務(wù)邏輯就被切換到創(chuàng)建Handler所在的線程中去執(zhí)行了;

⑦Looper的工作原理:Looper在Android的消息機(jī)制中扮演著消息循環(huán)的角色,具體來(lái)說(shuō)就是它會(huì)不停地從MessageQueue中查看是否有新消息,如果有新消息就會(huì)立刻處理,否則就一直阻塞在那里。注意關(guān)注一些重要的Looper的方法:

  • Looper.prepare()-為當(dāng)前線程創(chuàng)建一個(gè)Looper;

  • Looper.loop()-開(kāi)啟消息循環(huán),只有調(diào)用該方法,消息循環(huán)系統(tǒng)才會(huì)開(kāi)始循環(huán);

  • Looper.prepareMainLooper()-為主線程也就是ActivityThread創(chuàng)建Looper使用;

  • Looper.getMainLooper()-通過(guò)該方法可以在任意地方獲取到主線程的Looper;

  • Looper.quit() Looper.quitSafely()-退出Looper,自主創(chuàng)建的Looper建議在不使用的時(shí)候退出

⑧ActivityThread主線程通過(guò)ApplicationThread和AMS進(jìn)行進(jìn)程間通信

以上是“Android中Handler、Thread、HandlerThread的區(qū)別有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI