實例分析Android中HandlerThread線程用法

一、HandlerThread的介紹及使用舉例             

10余年的鼓樓網站建設經驗,針對設計、前端、開發、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。營銷型網站的優勢是能夠根據用戶設備顯示端的尺寸不同,自動調整鼓樓建站的顯示方式,使網站能夠適用不同顯示終端,在瀏覽器中調整網站的寬度,無論在任何一種瀏覽器上瀏覽網站,都能展現優雅布局與設計,從而大程度地提升瀏覽體驗。創新互聯從事“鼓樓網站設計”,“鼓樓網站推廣”以來,每個客戶項目都認真落實執行。

HandlerThread是什么鬼?其本質就是一個線程,但是HandlerThread在啟動的時候會幫我們準備好一個Looper,并供外界使用,說白了就是使我們在子線程中更方便的使用Handler,比如沒有HandlerThread我們要在子線程使用Handler,寫法如下:

private Handler mHandler;
    @Override
     public void run() {
        super.run();
         Looper.prepare();
         mHandler = new Handler(){
             @Override
             public void handleMessage(Message msg) {
             }
         };
         Looper.loop();
}

有了HandlerThread就不用我們自己管理Looper了,至于為什么分析源碼的時候就明白了。

HandlerThread使用簡單介紹:

首先我們要初始化HandlerThread然后調用其start方法,也就是開啟線程:

mHandlerThread = new HandlerThread("mHandlerThread");//這里的mHandlerThread其實就是線程的名字
mHandlerThread.start();

接下來初始化一個Handler并且將mHandlerThread中的Looper作為構造函數參數傳遞給Handler:

mHandler = new Handler(mHandlerThread.getLooper())

這樣就保證了Hnadler運行在子線程。并且需要在適合的時機調用HandlerThread的quit方法或quitSafely方法,如Activity銷毀的時候:

@Override
protected void onDestroy() {
   //
   super.onDestroy();
   //釋放資源
   mHandlerThread.quit();
}

quit()與quitSafely()方法比較(這里只說一些結論,源碼可以自己查看):

相同點:

調用之后MessageQueue消息隊列均不在接受新的消息加入隊列。

不同點:

quit方法把MessageQueue消息池中所有的消息全部清空。quitSafely方法只會清空MessageQueue消息池中所有的延遲消息(延遲消息是指通過sendMessageDelayed或postDelayed等方法發送的消息),非延遲消息則不清除繼續派發出去讓Handler去處理。

接下來我們完整看一下HandlerThread例子源碼:

 public class MainActivity extends Activity {
     private HandlerThread mHandlerThread;
     private Handler mHandler;
     private boolean flag;
     //
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
        mHandlerThread = new HandlerThread("mHandlerThread");
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper()) {
             @Override
             public void handleMessage(Message msg) {
                 //
                 try {
                     Thread.sleep(2000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 if(flag){
                     Log.i("HandlerThread", "更新:"+new Random().nextInt(1000));
                 }
                 mHandler.sendEmptyMessage(1);
             }
         };
     }
     @Override
     protected void onResume() {
         //
         super.onResume();
         flag = true;
         mHandler.sendEmptyMessage(1);
     }
     @Override
     protected void onPause() {
         //
         super.onPause();
         flag = false;
     }
     @Override
     protected void onDestroy() {
         //
         super.onDestroy();
         //釋放資源
         mHandlerThread.quit();
     }
}

運行程序就會在控制臺看到每隔兩秒有Log打出。至于HandlerThrea的使用就到此為止了,看懂上面小例子就差不多了。

二、HandlerThread的源碼分析

HandlerThread源碼非常簡短,出去注釋不到100行,這里就直接全部貼出來了:

 public class HandlerThread extends Thread {
     int mPriority;
     int mTid = -1;
    Looper mLooper;
     public HandlerThread(String name) {
         super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
     /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from
     * {@link android.os.Process} and not from java.lang.Thread.
      */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
     }
    /**
      * Call back method that can be explicitly overridden if needed to execute some
      * setup before Looper loops.
     */
     protected void onLooperPrepared() {
     }
    @Override
    public void run() {
         mTid = Process.myTid();
         Looper.prepare();
         synchronized (this) {
            mLooper = Looper.myLooper();
             notifyAll();
         }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
         Looper.loop();
         mTid = -1;
     }
     /**
      * This method returns the Looper associated with this thread. If this thread not been started
      * or for any reason is isAlive() returns false, this method will return null. If this thread
      * has been started, this method will block until the looper has been initialized. 
      * @return The looper.
      */
     public Looper getLooper() {
         if (!isAlive()) {
             return null;
         }
         // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
             while (isAlive() && mLooper == null) {
                try {
                    wait();
               } catch (InterruptedException e) {
                 }
            }
        }
         return mLooper;
     }
     public boolean quit() {
        Looper looper = getLooper();
         if (looper != null) {
             looper.quit();
             return true;
         }
         return false;
     }
     public boolean quitSafely() {
         Looper looper = getLooper();
         if (looper != null) {
             looper.quitSafely();
             return true;
         }
         return false;
     }
     /**
      * Returns the identifier of this thread. See Process.myTid().
      */
     public int getThreadId() {
         return mTid;
     }
 }

看第一行就知道了其本質就是一個線程。

6-9行以及17-20行構造函數,也很簡單,就是初始化的時候我們可以定義線程名字,還可以傳入線程優先級。

初始化完成,緊接著調用start()開發線程就會執行run方法邏輯。

30-41行代碼,最重要的就是調用Looper.prepare()以及Looper.loop()方法為我們在子線程準備好一個Looper。并且用變量mLooper記錄,調用getLooper()方法的時候返回。

但是,細心的你肯定發現run()方法中有個notifyAll(),getLooper()中有個wait()為什么要加這些鳥玩意?

大家發現沒在HandlerThread 例子中Handler的創建是在主線程完成的,創建的時候需要調用HandlerThread的getLooper()獲取mLooper作為參數傳遞給Handler的構造函數,而Looper的創建是在子線程中創建的,這里就有線程同步問題了,比如我們調用getLooper()的時候HandlerThread中run()方法還沒執行完,mLooper變量還未賦值,此時就執行了wait()等待邏輯,一直等到run()方法中mLooper被賦值,之后立即執行notifyAll(),然后getLooper()就可以正確返回mLooper了。

明白了吧,不明的話這里需要花些時間好好理解下,好了源碼主要部分就分析完了,看到這里相信你對HandlerThread有了一定的了解了。

HandlerThread 還是比較簡單理解的,好了,本篇到此為止,希望對你有幫助。

分享名稱:實例分析Android中HandlerThread線程用法
URL地址:http://m.kartarina.com/article48/jedoep.html

成都網站建設公司_創新互聯,為您提供域名注冊網站制作響應式網站全網營銷推廣企業建站品牌網站制作

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

h5響應式網站建設
主站蜘蛛池模板: 亚洲欧洲精品无码AV| 精品爆乳一区二区三区无码av| 韩国精品一区二区三区无码视频| 亚洲av无码成人影院一区| 国产精品免费看久久久无码| 国产精品无码久久综合| 精品久久久久久中文字幕无码| 中文无码熟妇人妻AV在线| 亚洲精品无码aⅴ中文字幕蜜桃| 亚洲熟妇少妇任你躁在线观看无码| 亚洲AV永久纯肉无码精品动漫| 无码h黄肉3d动漫在线观看 | 一本大道无码日韩精品影视| 亚洲动漫精品无码av天堂| 国产精品无码久久四虎| 无码人妻精品一区二区三区夜夜嗨 | 亚洲a∨无码精品色午夜| 中文字幕av无码一区二区三区电影| 日韩精品无码熟人妻视频| 国产AⅤ无码专区亚洲AV| 成人免费无码大片a毛片软件| 久久精品亚洲AV久久久无码| 野花在线无码视频在线播放 | 精品久久久久久久无码久中文字幕| 午夜不卡无码中文字幕影院| 少妇性饥渴无码A区免费 | 无码人妻精品一区二区三区夜夜嗨| 国产成人亚洲综合无码| 色欲aⅴ亚洲情无码AV| 无码专区永久免费AV网站| 亚洲国产成人精品无码区在线秒播| 亚洲精品无码av人在线观看| 久久精品无码一区二区app| 免费无码婬片aaa直播表情| 久久久久无码精品国产h动漫| 亚洲爆乳AAA无码专区| 亚洲AV永久无码精品放毛片| 亚洲成a人无码亚洲成www牛牛 | 日韩精品中文字幕无码一区| 亚洲中文无码a∨在线观看| 无码任你躁久久久久久老妇App |