手寫Handler

什么是Handler?

Handler主要用于異步消息的處理可婶,當發(fā)出一個消息后,首先進入一個消息隊列兜蠕,發(fā)送消息的函數(shù)即刻返回扰肌,而另外一個部分在消息隊列中逐一將消息取出抛寝,然后對消息進行處理熊杨。

子線程進行耗時操作>>>>>>>>>sendMessage(Message)>>>>>>>>UI線程

1.handler內(nèi)存泄漏測試

2.為什么不能在子線程創(chuàng)建handler

3.textview.setText(" ")只能在主線程執(zhí)行是錯誤的曙旭。

4.new handler()兩種寫法的區(qū)別

5.ThreadLocal的用法和原理

answer1 在子線程中發(fā)送消息時,如果要延時采用sendMessageDelayed(),當onDestory()時,removeMessage(),或者SyetemClock.sleep()系統(tǒng)延遲時晶府,在onDestory()時桂躏,將handler=null置空

answer2 其實在有些手機上面是可以的,因為廠商在底層修改了源碼川陆,但是原生系統(tǒng)中剂习,當new hander時,threadLocal回去threadLocalMap中去取looper较沪,而looper是全局的唯一變量已經(jīng)給了主線程鳞绕,當子線程再去去的時候就已經(jīng)取不到了。

answer3 其實setText(" ")執(zhí)行速度當刷新頁面的速度快于checkThread()的速度就不會拋異常尸曼,如果延時或者采用土司就會拋出異常们何。為了保險起見在子線程中不應該setText(" "),但是這種說法太過絕對。

answer4 一種是重寫handlerMessage(),另一種是將回調(diào)接口CallBack當作參數(shù)傳入new Handler構造方法控轿。

answer5 從threadLocalMap中獲取key value冤竹。key是線程,value是looper茬射。ThreadLocal有一個全局唯一靜態(tài)變量鹦蠕,當ThreadActivity創(chuàng)建時就已經(jīng)創(chuàng)建。

Handler原理在抛,工作流程

第一步:ActivityThread中的main(),Looper.prepareMainLooper()>>>>prepare()>>>>sThreadLocal.set(new Looper)創(chuàng)建全局唯一Looper對象钟病,在Looper構造方法中{new MessageQueue()}創(chuàng)建全局唯一消息隊列

第二步:在activity中,new Handler()重寫handlerMessage();在創(chuàng)建對象的過程中刚梭,將全局的messageQueue對象賦值給Handler中的messageQueue档悠,再從全局線程池中取出主線程Looper,sThreadLocal.get()。

?? 發(fā)送消息 handler.sendMessage(message)>>>>將消息放入隊列中望浩,queue.enqueueMessage(msg)>>>>mMeeages=msg?

?? 取消息 ActivityThread中的main(),looper.loop()中有一個輪詢器一直在工作//獲取looper對象 Looper me=getLooper(),獲取消息隊列辖所,MessageQueue queue=me.mQueue;//從消息隊列取出消息Message msg=mQueue.next();調(diào)用handler的方法,msg.targe.dispatchMessage(msg);

自己手寫Handler流程源碼,只是一個大致工作流程磨德,不考慮健壯性等因素

1.ActivityThread

public class ActivityThread {

@Test

? ? public void main() {

//創(chuàng)建全局唯一的,主線程的Looper對象缘回,以及messageQueue消息隊列對象。

? ? ? ? Looper.prepare();

? ? ? ? //模擬activity中典挑,創(chuàng)建handler對象

? ? ? ? final Handler handler =new Handler() {

@Override

? ? ? ? ? ? public void handlerMessage(Message message) {

super.handlerMessage(message);

? ? ? ? ? ? ? ? System.out.println(message.obj.toString());

? ? ? ? ? ? }

};

? ? ? ? //消費消息酥宴,回調(diào)方法(接口方法)

//子線程發(fā)送消息

? ? ? ? new Thread(new Runnable() {

@Override

? ? ? ? ? ? public void run() {

Message messa=new Message();

? ? ? ? ? ? ? ? messa.obj="hello handler";

? ? ? ? ? ? ? ? handler.sendMessage(messa);

? ? ? ? ? ? }

}).start();

? ? ? ? //輪詢。取出消息

? ? ? ? Looper.loop();

? ? }

}

2.Looper

public class Looper {

public MessageQueuemQueue;

? ? static final ThreadLocalsThreadLocal =new ThreadLocal<>();

? ? private Looper() {

mQueue =new MessageQueue();

? ? }

public static void prepare() {

//主線程唯一一個Loop對象

? ? ? ? if (sThreadLocal.get() !=null) {

throw new RuntimeException("Only one Looper may be created per thread");

? ? ? ? }

//應用啟動時您觉,初始化賦值

? ? ? ? sThreadLocal.set(new Looper());

? ? }

//輪詢拙寡,提取消息

? ? public static void loop() {

//從全局ThreadlocalMap()中獲取全局唯一Looper對象

? ? ? ? Looper me =getLooper();

? ? ? ? //從Looper對象中獲取全局唯一的消息隊列對象

? ? ? ? final MessageQueue queue = me.mQueue;

? ? ? ? Message resultMessage;

? ? ? ? while (true) {

Message msg = queue.next();

? ? ? ? ? ? if (msg !=null) {

msg.targe.dispatchMessage(msg);

? ? ? ? ? ? }

}

}

public static LoopergetLooper() {

return sThreadLocal.get();

? ? }

}

3.Message

public class Message {

public? Objectobj;

? public Handlertarge;

? ? @Override

? ? public StringtoString() {

return obj.toString();

? ? }

}

4.//消息隊列

public class MessageQueue {

//阻塞隊列

? ? BlockingQueueblockingQueue =new ArrayBlockingQueue<>(50);

? ? //將message存入消息隊列

? ? public void enqueueMessag(Message message) {

try {

blockingQueue.put(message);

? ? ? ? }catch (InterruptedException e) {

e.printStackTrace();

? ? ? ? }

}

//從消息隊列取出message

? ? public Messagenext() {

try {

return blockingQueue.take();

? ? ? ? }catch (InterruptedException e) {

e.printStackTrace();

? ? ? ? }

return null;

? ? }

}

5Handler

public class Handler {

private LoopermLooper;

? ? private MessageQueuemQueue;

? ? public Handler() {

mLooper = Looper.getLooper();

? ? ? ? if(mLooper==null){

throw? new RuntimeException("Can't create handler inside thread " + Thread.currentThread()

+" that has not called Looper.prepare()");

? ? ? ? }

mQueue=mLooper.mQueue;

? ? }

public void handlerMessage(Message message) {

}

public void sendMessage(Message message) {

enqueueMessage(message);

? ? }

private void enqueueMessage(Message message) {

message.targe=this;

? ? ? ? mQueue.enqueueMessag(message);

? ? }

public void dispatchMessage(Message msg) {

handlerMessage(msg);

? ? }

}

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市琳水,隨后出現(xiàn)的幾起案子肆糕,更是在濱河造成了極大的恐慌般堆,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诚啃,死亡現(xiàn)場離奇詭異淮摔,居然都是意外死亡,警方通過查閱死者的電腦和手機始赎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門和橙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人造垛,你說我怎么就攤上這事魔招。” “怎么了五辽?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵仆百,是天一觀的道長。 經(jīng)常有香客問我奔脐,道長俄周,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任髓迎,我火速辦了婚禮峦朗,結果婚禮上,老公的妹妹穿的比我還像新娘排龄。我一直安慰自己波势,他們只是感情好,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布橄维。 她就那樣靜靜地躺著尺铣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪争舞。 梳的紋絲不亂的頭發(fā)上凛忿,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音竞川,去河邊找鬼店溢。 笑死,一個胖子當著我的面吹牛委乌,可吹牛的內(nèi)容都是我干的床牧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼遭贸,長吁一口氣:“原來是場噩夢啊……” “哼戈咳!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤著蛙,失蹤者是張志新(化名)和其女友劉穎删铃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體册踩,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡泳姐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年效拭,在試婚紗的時候發(fā)現(xiàn)自己被綠了暂吉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡缎患,死狀恐怖慕的,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挤渔,我是刑警寧澤肮街,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站判导,受9級特大地震影響嫉父,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜眼刃,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一绕辖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧擂红,春花似錦仪际、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至变秦,卻和暖如春成榜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蹦玫。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工伦连, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钳垮。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓惑淳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饺窿。 傳聞我的和親對象是個殘疾皇子歧焦,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

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