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