3.Handler使用及注意事項

常見用法:

  • Message盡量復(fù)用,obtain從消息池中取兄春。
//消息池中取出的
public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null; //從sPool中取出一個Message對象澎剥,并消息鏈表斷開
            m.flags = 0; // 清除in-use flag
            sPoolSize--; //消息池的可用大小進行減1操作
            return m;
        }
    }
    return new Message(); // 當消息池為空時,直接創(chuàng)建Message對象
}

假如有個Runnbal包裝的Message用完以后在消息池中赶舆,obtain拿到后哑姚,設(shè)置what,obj等信息芜茵,那么現(xiàn)在這個msg有callback叙量,還有what等信息。會不會在分發(fā)的時候夕晓,calllBack != null宛乃,那又繼續(xù)調(diào)用了runnable的run方法了?并沒有達到這個msg的目的啊。
測試post的50個runnable的消息征炼,obtain取了300個新的析既,并沒有復(fù)用到runnable的。 因該是怎樣呢谆奥?

  • getMainLooper()/view.post(runnable)/handler.post(runnable)
  • activity.runOnUiThread
public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            //非UI線程眼坏,到handler執(zhí)行
            mHandler.post(action);
        } else {
            //UI線程直接run
            action.run();
        }
    }
  • onCreat方法完成之前,在非UI線程更改UI不會報錯酸些。
  • loop死循環(huán)宰译,后面的代碼無法執(zhí)行∑嵌可退出沿侈。
@OnClick({R.id.test_btn_1, R.id.test_btn_2})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.test_btn_1:
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      Looper.prepare();
                      handler = new TestHandler();
                      //打印log
                      handler.sendEmptyMessage(11);
                      Looper.loop();
                      //不執(zhí)行,loop死循環(huán)市栗,執(zhí)行不到
                      Log.e(TAG, "run: after loop" );
                  }
              }).start();
                break;
            case R.id.test_btn_2:
                //退出缀拭,繼續(xù)向下執(zhí)行,打印log
                handler.getLooper().quit();
                break;
        }
    }
  • ActivityThread不會影響:UI線程中ActivityThread就是消息循環(huán)填帽,各種onResume/onCreate方法蛛淋,都是通過handler發(fā)送消息調(diào)用更新的,可以把這些方法的執(zhí)行看作一個個消息篡腌,如果某個消息處理實踐過程褐荷,就可能會影響UI刷新造成卡頓。(涉及到Binder/進程/Linux管道等知識嘹悼,馬達現(xiàn)在段位不夠叛甫,看不懂)
public static void main(String[] args) {  
    ...
    Looper.prepareMainLooper();  
    
    ActivityThread thread = new ActivityThread();  
    thread.attach(false);  
    if (sMainThreadHandler == null) {  
        sMainThreadHandler = thread.getHandler();  
    }  
    AsyncTask.init();  
    if (false) {  
        Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));  
    }  
    
    Looper.loop();  
    throw new RuntimeException("Main thread loop unexpectedly exited");  
}  
  • 異常方面

當 Activity finish 時,在 onDestroy 方法中釋放了一些資源。此時 Handler 執(zhí)行到 handlerMessage 方法,但相關(guān)資源已經(jīng)被釋放,從而引起空指針的異常绘迁。
避免

如果是使用 handlerMessage合溺,則在方法中加try catch。
如果是用 post 方法缀台,則在Runnable方法中加try catch。

  • 內(nèi)存泄露

handler可能引用外部累對象activity哮奇,如果activity關(guān)閉膛腐,handler沒執(zhí)行完,從而引起activity內(nèi)存泄漏鼎俘。

/**
     為避免handler造成的內(nèi)存泄漏
     1哲身、使用靜態(tài)的handler,對外部類不保持對象的引用
     2贸伐、但Handler需要與Activity通信勘天,所以需要增加一個對Activity的弱引用
    */
      private static class MyHandler extends Handler {
        private final WeakReference<Activity> mActivityReference;    

        MyHandler(Activity activity) {
            this.mActivityReference = new WeakReference<Activity>(activity);
        }

        @Override
            public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MainActivity activity = (MainActivity) mActivityReference.get();  //獲取弱引用隊列中的activity
            switch (msg.what) {    //獲取消息,更新UI
                case 1:
                    byte[] data = (byte[]) msg.obj;
                    activity.threadIv.setImageBitmap(activity.getBitmap(data));
                    break;
            }
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脯丝,隨后出現(xiàn)的幾起案子商膊,更是在濱河造成了極大的恐慌,老刑警劉巖宠进,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晕拆,死亡現(xiàn)場離奇詭異,居然都是意外死亡材蹬,警方通過查閱死者的電腦和手機实幕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堤器,“玉大人昆庇,你說我怎么就攤上這事≌⒗#” “怎么了凰锡?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長圈暗。 經(jīng)常有香客問我掂为,道長,這世上最難降的妖魔是什么员串? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任勇哗,我火速辦了婚禮,結(jié)果婚禮上寸齐,老公的妹妹穿的比我還像新娘欲诺。我一直安慰自己,他們只是感情好渺鹦,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布扰法。 她就那樣靜靜地躺著,像睡著了一般毅厚。 火紅的嫁衣襯著肌膚如雪塞颁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天吸耿,我揣著相機與錄音祠锣,去河邊找鬼。 笑死咽安,一個胖子當著我的面吹牛伴网,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播妆棒,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼澡腾,長吁一口氣:“原來是場噩夢啊……” “哼沸伏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起动分,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤毅糟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后刺啦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體留特,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年玛瘸,在試婚紗的時候發(fā)現(xiàn)自己被綠了蜕青。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡糊渊,死狀恐怖右核,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渺绒,我是刑警寧澤贺喝,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站宗兼,受9級特大地震影響躏鱼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殷绍,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一染苛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧主到,春花似錦茶行、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至牧牢,卻和暖如春看锉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背结执。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工度陆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人献幔。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像趾诗,于是被迫代替她去往敵國和親蜡感。 傳聞我的和親對象是個殘疾皇子蹬蚁,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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