android Handler的使用(一)
Handler的使用(一)
Handler基本概念:
Handler主要用于異步消息的處理:當(dāng)發(fā)出一個(gè)消息之后,首先進(jìn)入一個(gè)消息隊(duì)列,發(fā)送消息的函數(shù)即刻返回,而另外一個(gè)部分逐個(gè)的在消息隊(duì)列中將消息取出,然后對(duì)消息進(jìn)行出來(lái),就是發(fā)送消息和接收消息不是同步的處理。
這種機(jī)制通常用來(lái)處理相對(duì)耗時(shí)比較長(zhǎng)的操作。
使用一個(gè)例子簡(jiǎn)單的來(lái)介紹一下Handler。
示例1:一個(gè)應(yīng)用程序中有2個(gè)按鈕(start、end),當(dāng)點(diǎn)擊start按鈕時(shí),執(zhí)行一個(gè)線程,這個(gè)線程在控制臺(tái)輸出一串字符串,并且每隔3秒再執(zhí)行一次線程,直到點(diǎn)擊end按鈕為止,線程停止。
下圖為這個(gè)應(yīng)用程序的界面:
下圖為執(zhí)行程序時(shí)控制臺(tái)的輸出:
開(kāi)發(fā)步驟:
1、 新建一個(gè)Android應(yīng)用程序
2、 在布局文件中添加2個(gè)Button控件標(biāo)簽,并為其設(shè)置屬性和值
3、 在Activity中,聲明控件變量并根據(jù)id獲得控件對(duì)象
4、 在Activity中,創(chuàng)建一個(gè)Handler對(duì)象
5、 在Activity中,創(chuàng)建一個(gè)Runnable對(duì)象
a) 以匿名內(nèi)部類的方式
b) 將要執(zhí)行的操作寫(xiě)在Runnable對(duì)象中的run()方法中
i. 打印出一句話
ii. 調(diào)用Runnable對(duì)象的postDelayed()方法
6、 在Activity中,編寫(xiě)start按鈕需要的監(jiān)聽(tīng)器,并綁定
a) 在這個(gè)監(jiān)聽(tīng)器的Onclick()方法中,調(diào)用Handler的post()方法,將要執(zhí)行的線程對(duì)象放到隊(duì)列當(dāng)中。
7、 在Activity中,編寫(xiě)end按鈕需要的監(jiān)聽(tīng)器,并幫定
a) 在這個(gè)監(jiān)聽(tīng)器的Onclick()方法中,調(diào)用Handler的removeCallbacks ()方法,刪除隊(duì)列當(dāng)中未執(zhí)行的線程對(duì)象。
b)
下面是Activity的代碼:
上面是一個(gè)最簡(jiǎn)單的例子,下面再看另外一個(gè)例子。
示例2:一個(gè)應(yīng)用程序中有一個(gè)進(jìn)度條和一個(gè)按鈕,當(dāng)點(diǎn)擊按鈕后,每隔一秒鐘進(jìn)度條前進(jìn)一部分。
下圖為應(yīng)用程序的運(yùn)行效果圖:
開(kāi)發(fā)步驟:
1、 新建一個(gè)Android應(yīng)用程序
2、 在布局文件中添加一個(gè)progressBar和一個(gè)Button,并為其設(shè)置屬性和值
3、 在Activity中,聲明控件變量并根據(jù)id獲得控件對(duì)象
4、 創(chuàng)建線程對(duì)象
a) 通過(guò)匿名內(nèi)部類的方式
b) 在編寫(xiě)完了5、6步之后再來(lái)繼續(xù)編寫(xiě)這個(gè)線程對(duì)象里的操作
i. 聲明一個(gè)變量用來(lái)設(shè)置進(jìn)度條的進(jìn)度
ii. 重寫(xiě)線程類的run方法(),里面編寫(xiě)要執(zhí)行的操作
1. 打印一個(gè)字符串
2. 進(jìn)度條的值增加
3. 得到一個(gè)消息對(duì)象
4. 設(shè)置消息對(duì)象arg1的值
5. 讓線程休眠一秒鐘
6. 將消息對(duì)象放入到消息隊(duì)列中
7. 判斷,如果進(jìn)度條的值等于100,則將線程對(duì)象從隊(duì)列中移除。
5、 創(chuàng)建Handler對(duì)象
a) 與示例1不同的地方是,這里是通過(guò)匿名內(nèi)部類的方式來(lái)聲明的,而示例1是直接new出來(lái)的對(duì)象
b) 重寫(xiě)Handler對(duì)象的handlerMessage(Message msg)方法
i. 這個(gè)方法傳入了一個(gè)Message對(duì)象,即消息對(duì)象,首先設(shè)置進(jìn)度條的進(jìn)度(這個(gè)值是Messag對(duì)象里面的一個(gè)成員變量arg1)。
ii. 將要執(zhí)行的線程對(duì)象放入到隊(duì)列當(dāng)中
6、 編寫(xiě)B(tài)utton需要的監(jiān)聽(tīng)器,并綁定
a) 設(shè)置進(jìn)度條為顯示狀態(tài)
b) 將要執(zhí)行的線程對(duì)象放入到隊(duì)列當(dāng)中
下面是Activity的代碼:
項(xiàng)目源碼已經(jīng)上傳到附件了,有需要的可下載。
不知道大家有沒(méi)有弄明白哈,我自己都寫(xiě)得暈暈乎乎的了,沒(méi)辦法啊語(yǔ)文寫(xiě)作能力不咋地,汗~
這里其實(shí)有一點(diǎn)我沒(méi)有弄明白,就是當(dāng)進(jìn)度條的值等于100的時(shí)候,就將線程對(duì)象從隊(duì)列中移除,從而停止線程的運(yùn)行;這個(gè)在示例1中是沒(méi)有問(wèn)題的, 當(dāng)點(diǎn)擊end按鈕,線程停止;但是在示例2例子中,當(dāng)進(jìn)度條的值等于100了,可是卻沒(méi)有停止,還是在繼續(xù)的運(yùn)行,每隔一秒就執(zhí)行一個(gè)線程,不知道這是為 什么,研究了好一會(huì)兒都沒(méi)弄明白,希望各位知道的可以跟我說(shuō)說(shuō)哈,咱們有機(jī)會(huì)多探討探討、多交流交流!
?
評(píng)論
16 樓 qiongqiong421122 2014-07-24?? 416849838 寫(xiě)道 回答三樓? 不行,因?yàn)椴荒茉谧泳€程里更新UIupdateThread里面的run方法是可以更新進(jìn)度條的,因?yàn)檫@里的操作相當(dāng)于在UI線程,只要稍微調(diào)整一下代碼,就可以做到三樓的要求。 15 樓 geniuz 2014-05-23?? 用Handler調(diào)用Runnable接口應(yīng)該並不是真的開(kāi)新線程,只是實(shí)現(xiàn)接口而已,Handler把run擺進(jìn)UI線程的looper運(yùn)行的,所以即使不用消息,在run用應(yīng)該也能處理UI的東西。 14 樓 鯉魚(yú)味美 2014-04-24??
??????? public void run() {?
??????? if(i<=100){
??????????? // TODO Auto-generated method stub?
?????????? Log.i("QiHang","Begin Thread");?
??????????? i+=10;?
??????????? //得到一個(gè)消息對(duì)象,Message類是android系統(tǒng)提供的?
??????????? Message msg = updateBarHandler.obtainMessage();?
??????????? //將Message對(duì)象的arg1參數(shù)的值設(shè)置為i?
??????????? msg.arg1 = i;?? //用arg1、arg2這兩個(gè)成員變量傳遞消息,優(yōu)點(diǎn)是系統(tǒng)性能消耗較少?
??????????? try{?
??????????????? Thread.sleep(1000); //讓當(dāng)前線程休眠1000毫秒?
??????????? }catch(InterruptedException ex){?
??????????????? ex.printStackTrace();?
??????????? }?
??????????? //將Message對(duì)象加入到消息隊(duì)列當(dāng)中?
??????????? updateBarHandler.sendMessage(msg);?
??????????? //如果i的值等于100?
?????????????
??????? }
??????? else{
??????? //將線程對(duì)象從隊(duì)列中移除?
??????????????? updateBarHandler.removeCallbacks(updateThread);
??????????????? Log.i("QiHang","End Thread");?
??????? }
??????? }
這樣也可以結(jié)束 13 樓 xh194910 2014-02-27?? 樓主,我來(lái)啦 12 樓 yong7356 2013-08-30?? 學(xué)習(xí)了。。。。。 11 樓 yong7356 2013-08-02?? 。。。。。。。。。。。。。。。。。。。。 10 樓 mengrenfeixiang 2012-12-08?? 例2會(huì)導(dǎo)致updateThread的run方法死循環(huán),原因如下:
當(dāng)i==100時(shí),執(zhí)行了下面幾行代碼
if (i == 100){?
??????????????? //將線程對(duì)象從隊(duì)列中移除?
??????????????? updateBarHandler.removeCallbacks(updateThread);??
??? }
看似updateThread線程從線程對(duì)象隊(duì)列中移除,不會(huì)再執(zhí)行了,但是執(zhí)行這幾行代碼前執(zhí)行了下面代碼
//將Message對(duì)象加入到消息隊(duì)列當(dāng)中?
updateBarHandler.sendMessage(msg);
這會(huì)導(dǎo)致下面的代碼被執(zhí)行
public void handleMessage(Message msg) {????
??????????? progressBar.setProgress(msg.arg1);????
?????????? updateBarHandler.post(updateThread);??? //將要執(zhí)行的線程放入到隊(duì)列當(dāng)中????
}
updateThread線程又加到線程對(duì)象隊(duì)列中,updateThread線程永遠(yuǎn)不會(huì)從線程對(duì)象隊(duì)列中移除,updateThread的run方法不斷的執(zhí)行,這就導(dǎo)致了死循環(huán)。
解決方案:
將 updateThread的run方法里的
if (i == 100){?
??????????????? //將線程對(duì)象從隊(duì)列中移除?
??????????????? updateBarHandler.removeCallbacks(updateThread);??
??? }
這幾行代碼移到updateBarHandler的handleMessage方法里,修改如下:
Handler updateBarHandler = new Handler(){?
??????? @Override?
??????? public void handleMessage(Message msg) {?
??????????? progressBar.setProgress(msg.arg1);?
??????????? if(msg.arg1==100){
?????????????????????? updateBarHandler.removeCallbacks(updateThread);??
??????????? }else{
????????????????????? updateBarHandler.post(updateThread);??? //將要執(zhí)行的線程放入到隊(duì)列當(dāng)中
??????????? }?
??????? }?
??? };?
我是通過(guò)調(diào)試查看代碼的執(zhí)行順序,發(fā)現(xiàn)這個(gè)問(wèn)題的 9 樓 jkzhao 2012-10-27?? Handler主要是用于子線程與主線程的通訊,子線程可以把消息發(fā)送到主線程的Looper,有主線程來(lái)處理。 8 樓 tracydeerge 2012-10-25?? 我覺(jué)得Handler大多用來(lái)作為線程池中的線程與主線程的通信工具! 7 樓 416849838 2011-11-25?? 回答三樓? 不行,因?yàn)椴荒茉谧泳€程里更新UI 6 樓 zhangjm123 2011-11-20?? 將 //如果i的值等于100?
??????????? if (i == 100){?
??????????????? //將線程對(duì)象從隊(duì)列中移除?
??????????????? updateBarHandler.removeCallbacks(updateThread);??
??????????? }?
刪了,寫(xiě)到如5樓寫(xiě)的那樣就行了!! 5 樓 sserf 2011-09-28?? 不錯(cuò),很全面,轉(zhuǎn)了! 4 樓 cj83226 2011-09-05?? Java代碼 ?
應(yīng)該是這樣吧。。。。 3 樓 wjb_forward 2011-03-24?? 請(qǐng)問(wèn)直接在run方法里面增加進(jìn)度條的進(jìn)度不行嗎,把i寫(xiě)成一個(gè)全局變量。 2 樓 meng_fan_zhen 2011-03-16?? hehez 寫(xiě)道 Java代碼 ?
我試了下,這個(gè)是好使的。
1樓的判斷條件是不是正好寫(xiě)反了? 1 樓 hehez 2011-03-04?? Java代碼 ?
就這段,我也出現(xiàn)和你一樣的狀況。我在網(wǎng)上搜了好多,有人說(shuō)是,removeCallbacks只是把updateThread這個(gè)線程從隊(duì)列中移除,但是并沒(méi)有停止線程。
然后網(wǎng)上也有人提供了一個(gè)修正方法,就是在下面這段代碼中間
添加一個(gè)判斷
我試了下,這個(gè)是好使的。
轉(zhuǎn)載于:https://www.cnblogs.com/xgjblog/p/3881470.html
總結(jié)
以上是生活随笔為你收集整理的android Handler的使用(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: cant find module exp
- 下一篇: android广告平台哪个好用,最新!5