子線程創(chuàng)建Handler

默認(rèn)情況下,ActivityThread類為我們創(chuàng)建的了主線程的Looper和消息隊列赴叹,所以當(dāng)你創(chuàng)建Handler之后發(fā)送消息的時候鸿染,消息的輪訓(xùn)和handle都是在ui線程進(jìn)行的。這種情況屬于子線程給主線程發(fā)消息乞巧,通知主線程更新ui...等牡昆,那么反過來,怎么才能讓主線程給子線程發(fā)消息摊欠,通知子線程做一些耗時邏輯丢烘??

Android的消息機(jī)制遵循三個步驟:
    1  創(chuàng)建當(dāng)前線程的Looper  
    2  創(chuàng)建當(dāng)前線程的Handler 
    3  調(diào)用當(dāng)前線程Looper對象的loop方法

那么如果我想創(chuàng)建非主線程的Handler并且發(fā)送消息些椒、處理消息播瞳,這一系列的操作我們應(yīng)該怎么辦?直接上代碼:

public class ChildThreadHandlerActivity extends Activity {
    private MyThread childThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);

        childThread = new MyThread();
        childThread.start();

        Handler childHandler = new Handler(childThread.childLooper){//這樣之后免糕,childHandler和childLooper就關(guān)聯(lián)起來了赢乓。
            public void handleMessage(Message msg) {
                
            };
        };
    }

    private class MyThread extends Thread{
        public Looper childLooper;

        @Override
        public void run() {
            Looper.prepare();//創(chuàng)建與當(dāng)前線程相關(guān)的Looper
            childLooper = Looper.myLooper();//獲取當(dāng)前線程的Looper對象
            Looper.loop();//調(diào)用此方法,消息才會循環(huán)處理
        }
    }
}

代碼如上石窑,我們依然循序Android的三步走戰(zhàn)略牌芋,完成了子線程Handler的創(chuàng)建,難道這樣創(chuàng)建完了松逊,就可以發(fā)消息了么躺屁?發(fā)的消息在什么線程處理?一系列的問題经宏,怎么辦犀暑?看代碼Q被鳌!耐亏!運(yùn)行上述代碼徊都,我們發(fā)現(xiàn)一個問題,就是此代碼一會崩潰广辰、一會不崩潰暇矫,通過查看日志我們看到崩潰的原因是空指針。誰為空择吊?李根??查到是我們的Looper對象干发,怎么會那朱巨?我不是在子線程的run方法中初始化Looper對象了么史翘?話是沒錯枉长,但是你要知道,當(dāng)你statr子線程的時候琼讽,雖然子線程的run方法得到執(zhí)行必峰,但是主線程中代碼依然會向下執(zhí)行,造成空指針的原因是當(dāng)我們new Handler(childThread.childLooper)的時候钻蹬,run方法中的Looper對象還沒初始化吼蚁。當(dāng)然這種情況是隨機(jī)的,所以造成偶現(xiàn)的崩潰问欠。

那怎么辦肝匆?難道我們不能創(chuàng)建子線程Handler ?顺献?旗国?No!!!No!!!No!!!,你能想到的Android早就為我們實(shí)現(xiàn)好了注整,HandlerThread類就是解決這個問題的關(guān)鍵所在能曾,看代碼!V坠臁寿冕!

public class HandlerThreadActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        TextView textView = (TextView) findViewById(R.id.tv);
        textView.setText("HandlerThreadActivity.class");

        HandlerThread handlerThread = new HandlerThread("HandlerThread");
        handlerThread.start();

        Handler mHandler = new Handler(handlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d("HandlerThreadActivity.class","uiThread2------"+Thread.currentThread());//子線程
            }
        };

        Log.d("HandlerThreadActivity.class","uiThread1------"+Thread.currentThread());//主線程
        mHandler.sendEmptyMessage(1);
    }
}

創(chuàng)建HandlerThread對象的時候,有個參數(shù)椒袍,是指定線程名字的驼唱。上面的代碼不管運(yùn)行多少次都不會奔潰!>允睢曙蒸!并且這種方法創(chuàng)建的handler的handleMessage方法運(yùn)行在子線程中捌治。所以我們可以在這里處理一些耗時的邏輯。到此我們完成了主線程給子線程發(fā)通知纽窟,在子線程做耗時邏輯的操作肖油。

下面我們?nèi)タ纯丛创a,看看為什么使用HandlerThread就可以避免空指針那臂港?

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;
    }

HandlerThread類的getLooper方法如上森枪,我們看到當(dāng)我們獲取當(dāng)前線程Looper對象的時候,會先判斷當(dāng)前線程是否存活审孽,然后還要判斷Looper對象是否為空县袱,都滿足之后才會返回給我Looper對象,否則處于等待狀態(tài)S恿Α式散!既然有等待,那就有喚醒的時候打颤,在那里那暴拄??编饺?我們發(fā)現(xiàn)HandlerThread的run方法中乖篷,有如下代碼:

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

說明了什么那?透且?撕蔼?HandlerThread類start的時候,Looper對象就初始化了秽誊,并喚醒之前等待的鲸沮。所以HandlerThread很好的避免了之前空指針的產(chǎn)生。所以以后要想創(chuàng)建非主線程的Handler時锅论,我們用HandlerThread類提供的Looper對象即可讼溺。

原文鏈接:http://www.cnblogs.com/lang-yu/p/6228832.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市棍厌,隨后出現(xiàn)的幾起案子肾胯,更是在濱河造成了極大的恐慌,老刑警劉巖耘纱,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敬肚,死亡現(xiàn)場離奇詭異,居然都是意外死亡束析,警方通過查閱死者的電腦和手機(jī)艳馒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人弄慰,你說我怎么就攤上這事第美。” “怎么了陆爽?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵什往,是天一觀的道長。 經(jīng)常有香客問我慌闭,道長别威,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任驴剔,我火速辦了婚禮省古,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丧失。我一直安慰自己豺妓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布布讹。 她就那樣靜靜地躺著琳拭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炒事。 梳的紋絲不亂的頭發(fā)上臀栈,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天蔫慧,我揣著相機(jī)與錄音挠乳,去河邊找鬼。 笑死姑躲,一個胖子當(dāng)著我的面吹牛睡扬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播黍析,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼卖怜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阐枣?” 一聲冷哼從身側(cè)響起马靠,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔼两,沒想到半個月后甩鳄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡额划,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年妙啃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡揖赴,死狀恐怖馆匿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情燥滑,我是刑警寧澤渐北,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站铭拧,受9級特大地震影響腔稀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜羽历,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一焊虏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秕磷,春花似錦诵闭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至易桃,卻和暖如春褥琐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晤郑。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工敌呈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人造寝。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓磕洪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诫龙。 傳聞我的和親對象是個殘疾皇子析显,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評論 2 361