HandlerThread - 基本使用以及原理解析

本篇主要探討HandlerThread的基本使用以及原理解析

HandlerThread部分源碼

/**
 * 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.
 */
public class HandlerThread extends Thread {
    
    Looper mLooper;
    private @Nullable Handler mHandler;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    ...省略部分代碼
   @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    ...省略部分代碼

什么是HandlerThread?

正如源碼中,類注釋所述,一個擁有Looper的靈活線程,可以使用這個Looper來創(chuàng)建一個Handler.同常規(guī)線程一樣,Thread.start()仍必須調(diào)用蟀淮。

如果獲取Looper?

通過(HandlerThread對象).getLooper()即可獲取當(dāng)前HandlerThread線程中關(guān)聯(lián)的Looper.

如何退出或關(guān)閉ThreadHandler?

使用(HandlerThread對象).quit()(HandlerThread對象).quitSafely()退出杂伟。

Demo示例-如何使用HandlerThread负懦?

Demo代碼如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int HANDLER_THREAD_TASK_NO_1 = 1;
    //工作線程
    private HandlerThread mWorkThread;
    //通過HandlerThread中的Looper創(chuàng)建的Handler.
    private Handler mWorkHandler;
    private View mBtSendTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtSendTask = findViewById(R.id.bt_send_task);


        mBtSendTask.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Message message  = new Message();
                message.what = HANDLER_THREAD_TASK_NO_1;
                Bundle bundle = new Bundle();
                bundle.putString("account_id","123");
                bundle.putString("name","mike");
                message.setData(bundle);
                mWorkHandler.sendMessage(message);
            }
        });

        mWorkThread = new HandlerThread("work-Thread");

        //同普通的線程一樣,必須調(diào)用start,讓run方法運(yùn)行起來,初始化Handler.
        mWorkThread.start();

        //使用工作線程中的Looper(HandlerThread中的)來構(gòu)建一個Handler
        mWorkHandler = new Handler(mWorkThread.getLooper()){
            /*
             *  由于我們Handler的Looper是從HandlerThread中獲取到的,所以handleMessage會在子線中執(zhí)行拷肌。
             *  我們可以通過傳遞的Message中來獲取相關(guān)參數(shù),并執(zhí)行異步任務(wù)金度。
             * */
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                Log.e(TAG,"當(dāng)前線程N(yùn)ame: "+Thread.currentThread().getName()); //E/MainActivity: 當(dāng)前線程N(yùn)ame: work-Thread

                switch (msg.what) {
                    case HANDLER_THREAD_TASK_NO_1:

                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        Bundle data = msg.getData();
                        String account_id = data.getString("account_id");
                        String name = data.getString("name");
                        Log.e(TAG,"account: " + account_id + " name: "+name);
                        break;
                }
            }
        };
    }

    @Override
    protected void onDestroy() {
        //使用完成后,關(guān)閉線程
        mWorkThread.quit();
        //清除handler中的消息
        mWorkHandler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }
}

HandlerThread使用于哪些場景?

目前想到的是:有很多任務(wù)要處理,但任務(wù)必須異步并按順序處理的情況怕膛。

理由:HandlerThread的結(jié)合,提供了異步處理任務(wù)消息隊列,可以很好的對任務(wù)進(jìn)行排隊朴上。

IntentService - 源碼中的HandlerThread使用

IntentService,一種特殊的Service;可以處理異步耗時任務(wù),執(zhí)行完畢,自動關(guān)閉。

普通Service是在主UI線程線程執(zhí)行,如果我們需要進(jìn)行耗時操作,則必須通過 new Thread()來開啟一個線程來做耗時任務(wù)。

來看IntentService的源碼部分:

public abstract class IntentService extends Service {

    //HandlerThread中的Looper
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;

    //聲明一個類,ServiceHandler繼承自Handler
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        /*
          如果我們使用IntentService,要關(guān)注的只有onHandleIntent,因?yàn)樗鼒?zhí)行在子線程(工作線程)
          可以看到這里在調(diào)用完onHandleIntent后,即調(diào)用了 stopSelf().
          那么我們重點(diǎn)需要關(guān)注的即是handleMessage所處的線程偏螺。
        */
        @Override
        public void handleMessage(Message msg) {
            //收到傳遞的消息,進(jìn)行耗時任務(wù)
            onHandleIntent((Intent)msg.obj);
            //任務(wù)結(jié)束后關(guān)閉服務(wù)
            stopSelf(msg.arg1);
        }
    }

    //...省略代碼

    @Override
    public void onCreate() {
        super.onCreate();
        //這里創(chuàng)建了一個HandlerThread,并調(diào)用了start()
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        //獲取了HandlerThread中的 Looper()
        mServiceLooper = thread.getLooper();
        //將獲取到的Looper()用來創(chuàng)建ServiceHandler,那么ServiceHandler即允許在Looper所在的線程
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        //將我們傳遞的消息,發(fā)送到隊列里,等待傳遞
        mServiceHandler.sendMessage(msg);
    }

    //...省略代碼
}

可以看到IntentService中的代碼還是比較清晰的行疏。步驟:

1.創(chuàng)建HandlerThread,并調(diào)用start().
2.獲取HandlerThread中的Looper,創(chuàng)建任務(wù)處理的ServiceHandler,并重寫handleMessage().
3.外部啟動服務(wù),onStart()中獲取Intent中的數(shù)據(jù),并構(gòu)建Message對象,通過2中創(chuàng)建的ServiceHandler發(fā)送消息。
4.通過HandlerThreadrun()方法的Looper輪詢處理消息,調(diào)用ServiceHandlerhandleMessage().
5.我們在onHandleIntent()進(jìn)行耗時任務(wù)砖茸。結(jié)束后,服務(wù)自動關(guān)閉隘擎。

程序小白,偶爾寫寫,知識探究與記錄,有誤之處,望不吝賜教殴穴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凉夯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子采幌,更是在濱河造成了極大的恐慌劲够,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件休傍,死亡現(xiàn)場離奇詭異征绎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)磨取,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門人柿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人忙厌,你說我怎么就攤上這事凫岖。” “怎么了逢净?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵哥放,是天一觀的道長。 經(jīng)常有香客問我爹土,道長甥雕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任胀茵,我火速辦了婚禮社露,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘琼娘。我一直安慰自己峭弟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布轨奄。 她就那樣靜靜地躺著孟害,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挪拟。 梳的紋絲不亂的頭發(fā)上挨务,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼谎柄。 笑死丁侄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的朝巫。 我是一名探鬼主播鸿摇,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼劈猿!你這毒婦竟也來了拙吉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤揪荣,失蹤者是張志新(化名)和其女友劉穎筷黔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仗颈,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佛舱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挨决。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片请祖。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖脖祈,靈堂內(nèi)的尸體忽然破棺而出肆捕,到底是詐尸還是另有隱情,我是刑警寧澤撒犀,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布福压,位于F島的核電站,受9級特大地震影響或舞,放射性物質(zhì)發(fā)生泄漏荆姆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一映凳、第九天 我趴在偏房一處隱蔽的房頂上張望胆筒。 院中可真熱鬧,春花似錦诈豌、人聲如沸仆救。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彤蔽。三九已至,卻和暖如春庙洼,著一層夾襖步出監(jiān)牢的瞬間顿痪,已是汗流浹背镊辕。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚁袭,地道東北人征懈。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像揩悄,于是被迫代替她去往敵國和親卖哎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2018.3.31制定的夢想板删性,拖延了一個季度亏娜。 2018年上半年已經(jīng)過完,可是夢想板的內(nèi)容還有很多沒完成镇匀。 學(xué)習(xí)...
    Andy_d8c5閱讀 608評論 0 0
  • 深圳晚報訊(記者 方壯芳 通訊員 羅曉通)近日照藻,記者獲悉袜啃,在中國教育科學(xué)研究院汗侵、廣東省教育研究院、深圳市福田區(qū)教育...
    趙雪奎閱讀 820評論 0 0
  • 重組是資本市場最重要的炒作題材,重組不僅可以改變上市公司的股權(quán)結(jié)構(gòu)熟妓、主營業(yè)務(wù)等雪猪,而且會直接影響上市公司未來發(fā)展前景...
    0101f80f71e4閱讀 521評論 0 1
  • 真的很喜歡這個電影,于是把它畫了下來起愈。 臺詞也讓人心動? 《Gone with The Wind 亂世佳人》 1....
    冉遺_閱讀 1,081評論 5 6
  • 三歲兩個月的你只恨,特別喜歡和夏天一起玩。但是也特別容易爭起來抬虽,因?yàn)槟阏f這個官觅,他說那個。他的聲音大阐污,你開始哭起來(′;...
    無題人生閱讀 276評論 0 0