欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android中Handler、Thread、HandlerThread三者的區(qū)別

 更新時間:2021年10月25日 10:52:05   作者:Chin_style  
本文主要介紹了Android中Handler、Thread、HandlerThread三者的區(qū)別,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、前期知識儲備

(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ā)送和處理消息,通過它可以實現(xiàn)其他支線線程與主線程之間的消息通訊。

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

③HandlerThread:一個繼承自Thread的類HandlerThread,Android中沒有對Java中的Thread進行任何封裝,而是提供了一個繼承自Thread的類HandlerThread類,這個類對Java的Thread做了很多便利的封裝。

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

其實這個問題,最主要的關注點還是落在了HandlerThread類上,那么這個類到底有什么作用,所謂的便利封裝又體現(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對象start后可以獲得其Looper對象,并且使用這個Looper對象實例Handler,之后Handler就可以運行在其他線程中了。

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

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

                      

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

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

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

3) Message Queue( 消息隊列 ): 用來存放線程放入的消息。 

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

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

注:對應關系Thread(1):Looper(1):MessageQueen(1):Handler(n).

三、HandlerThread的使用

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

上代碼,具體實現(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)建與主線程關聯(lián)的Handler
        mainHandler = new Handler();
        /**
          * 步驟①:創(chuàng)建HandlerThread實例對象
          * 傳入?yún)?shù) = 線程名字,作用 = 標記該線程
          */
        mHandlerThread = new HandlerThread("handlerThread");
 
        /**
         * 步驟②:啟動線程
         */
        mHandlerThread.start();
 
        /**
         * 步驟③:創(chuàng)建工作線程Handler & 復寫handleMessage()
         * 作用:關聯(lián)HandlerThread的Looper對象、實現(xiàn)消息處理操作 & 與其他線程進行通信
         * 注:消息處理操作(HandlerMessage())的執(zhí)行線程 = mHandlerThread所創(chuàng)建的工作線程中執(zhí)行
         */
 
        workHandler = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg)
            {
                //設置了兩種消息處理操作,通過msg來進行識別
                switch(msg.what){
                    case 1:
                        try {
                            //延時操作
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 通過主線程Handler.post方法進行在主線程的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向工作線程的消息隊列發(fā)送消息
         * 在工作線程中,當消息循環(huán)時取出對應消息 & 在工作線程執(zhí)行相關操作
         */
        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = Message.obtain();
                msg.what = 1; //消息的標識
                msg.obj = "A"; // 消息的存放
                // 通過Handler發(fā)送消息到其綁定的消息隊列
                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)存泄露 清空消息隊列
    }
}

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

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

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

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

②Handler的運行需要底層的MessageQueue和Looper的支撐,Handler創(chuàng)建的時候會采用當前線程的Looper來構造消息循環(huán)系統(tǒng),而線程默認是沒有Looper的,如果需要使用Handler就必須為線程創(chuàng)建Looper;

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

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

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

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

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

  • Looper.prepare()-為當前線程創(chuàng)建一個Looper;
  • Looper.loop()-開啟消息循環(huán),只有調(diào)用該方法,消息循環(huán)系統(tǒng)才會開始循環(huán);
  • Looper.prepareMainLooper()-為主線程也就是ActivityThread創(chuàng)建Looper使用;
  • Looper.getMainLooper()-通過該方法可以在任意地方獲取到主線程的Looper;
  • Looper.quit() Looper.quitSafely()-退出Looper,自主創(chuàng)建的Looper建議在不使用的時候退出

⑧ActivityThread主線程通過ApplicationThread和AMS進行進程間通信

到此這篇關于Android中Handler、Thread、HandlerThread三者的區(qū)別的文章就介紹到這了,更多相關Android中Handler、Thread、HandlerThread三者的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Android入門之Menu組件的使用教程詳解

    Android入門之Menu組件的使用教程詳解

    這篇文章主要為大家詳細介紹了Android中常用的幾個Menu組件的使用教程,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的可以了解一下
    2022-11-11
  • 最新評論