日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android Handler的使用(一)

發(fā)布時(shí)間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android Handler的使用(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Handler的使用(一)

Handler基本概念:
Handler主要用于異步消息的處理:當(dāng)發(fā)出一個(gè)消息之后,首先進(jìn)入一個(gè)消息隊(duì)列,發(fā)送消息的函數(shù)即刻返回,而另外一個(gè)部分逐個(gè)的在消息隊(duì)列中將消息取出,然后對消息進(jìn)行出來,就是發(fā)送消息和接收消息不是同步的處理。
這種機(jī)制通常用來處理相對耗時(shí)比較長的操作。

使用一個(gè)例子簡單的來介紹一下Handler。
示例1:一個(gè)應(yīng)用程序中有2個(gè)按鈕(start、end),當(dāng)點(diǎn)擊start按鈕時(shí),執(zhí)行一個(gè)線程,這個(gè)線程在控制臺輸出一串字符串,并且每隔3秒再執(zhí)行一次線程,直到點(diǎn)擊end按鈕為止,線程停止。
下圖為這個(gè)應(yīng)用程序的界面:



下圖為執(zhí)行程序時(shí)控制臺的輸出:



開發(fā)步驟:
1、 新建一個(gè)Android應(yīng)用程序
2、 在布局文件中添加2個(gè)Button控件標(biāo)簽,并為其設(shè)置屬性和值
3、 在Activity中,聲明控件變量并根據(jù)id獲得控件對象
4、 在Activity中,創(chuàng)建一個(gè)Handler對象
5、 在Activity中,創(chuàng)建一個(gè)Runnable對象
a) 以匿名內(nèi)部類的方式
b) 將要執(zhí)行的操作寫在Runnable對象中的run()方法中
i. 打印出一句話
ii. 調(diào)用Runnable對象的postDelayed()方法
6、 在Activity中,編寫start按鈕需要的監(jiān)聽器,并綁定
a) 在這個(gè)監(jiān)聽器的Onclick()方法中,調(diào)用Handler的post()方法,將要執(zhí)行的線程對象放到隊(duì)列當(dāng)中。
7、 在Activity中,編寫end按鈕需要的監(jiān)聽器,并幫定
a) 在這個(gè)監(jiān)聽器的Onclick()方法中,調(diào)用Handler的removeCallbacks ()方法,刪除隊(duì)列當(dāng)中未執(zhí)行的線程對象。
b)
下面是Activity的代碼:

Java代碼 ?
  • package?android.handler;??
  • ??
  • import?android.app.Activity;??
  • import?android.os.Bundle;??
  • import?android.os.Handler;??
  • import?android.view.View;??
  • import?android.view.View.OnClickListener;??
  • import?android.widget.Button;??
  • ??
  • public?class?HandlerTest?extends?Activity?{??
  • ????/**?Called?when?the?activity?is?first?created.?*/??
  • ????private?Button?startButton;??
  • ????private?Button?endButton;??
  • ??????
  • ????@Override??
  • ????public?void?onCreate(Bundle?savedInstanceState)?{??
  • ????????super.onCreate(savedInstanceState);??
  • ????????setContentView(R.layout.main);??
  • ????????//根據(jù)id獲得控件對象??
  • ????????startButton?=?(Button)findViewById(R.id.startButton);??
  • ????????endButton?=?(Button)findViewById(R.id.endButton);??
  • ????????//為控件設(shè)置監(jiān)聽器??
  • ????????startButton.setOnClickListener(new?StartButtonListener());??
  • ????????endButton.setOnClickListener(new?EndButtonListener());??
  • ????}??
  • ??????
  • ????class?StartButtonListener?implements?OnClickListener{??
  • ????????public?void?onClick(View?v)?{??
  • ????????????//調(diào)用Handler的post()方法,將要執(zhí)行的線程對象放到隊(duì)列當(dāng)中??
  • ????????????handler.post(updateThread);??
  • ????????}??
  • ????}??
  • ??????
  • ????class?EndButtonListener?implements?OnClickListener{??
  • ????????public?void?onClick(View?v)?{??
  • ????????????//調(diào)用Handler的removeCallbacks()方法,刪除隊(duì)列當(dāng)中未執(zhí)行的線程對象??
  • ????????????handler.removeCallbacks(updateThread);??
  • ????????}??
  • ??????????
  • ????}??
  • ??????
  • ????//創(chuàng)建Handler對象??
  • ????Handler?handler?=?new?Handler();??
  • ????//新建一個(gè)線程對象??
  • ????Runnable?updateThread?=?new?Runnable(){??
  • ????????//將要執(zhí)行的操作寫在線程對象的run方法當(dāng)中??
  • ????????public?void?run(){??
  • ????????????System.out.println("updateThread");??
  • ????????????//調(diào)用Handler的postDelayed()方法??
  • ????????????//這個(gè)方法的作用是:將要執(zhí)行的線程對象放入到隊(duì)列當(dāng)中,待時(shí)間結(jié)束后,運(yùn)行制定的線程對象??
  • ????????????//第一個(gè)參數(shù)是Runnable類型:將要執(zhí)行的線程對象??
  • ????????????//第二個(gè)參數(shù)是long類型:延遲的時(shí)間,以毫秒為單位??
  • ????????????handler.postDelayed(updateThread,?3000);??
  • ????????}??
  • ????};??
  • }??

  • 上面是一個(gè)最簡單的例子,下面再看另外一個(gè)例子。
    示例2:一個(gè)應(yīng)用程序中有一個(gè)進(jìn)度條和一個(gè)按鈕,當(dāng)點(diǎn)擊按鈕后,每隔一秒鐘進(jìn)度條前進(jìn)一部分。
    下圖為應(yīng)用程序的運(yùn)行效果圖:



    開發(fā)步驟:
    1、 新建一個(gè)Android應(yīng)用程序
    2、 在布局文件中添加一個(gè)progressBar和一個(gè)Button,并為其設(shè)置屬性和值
    3、 在Activity中,聲明控件變量并根據(jù)id獲得控件對象
    4、 創(chuàng)建線程對象
    a) 通過匿名內(nèi)部類的方式
    b) 在編寫完了5、6步之后再來繼續(xù)編寫這個(gè)線程對象里的操作
    i. 聲明一個(gè)變量用來設(shè)置進(jìn)度條的進(jìn)度
    ii. 重寫線程類的run方法(),里面編寫要執(zhí)行的操作
    1. 打印一個(gè)字符串
    2. 進(jìn)度條的值增加
    3. 得到一個(gè)消息對象
    4. 設(shè)置消息對象arg1的值
    5. 讓線程休眠一秒鐘
    6. 將消息對象放入到消息隊(duì)列中
    7. 判斷,如果進(jìn)度條的值等于100,則將線程對象從隊(duì)列中移除。
    5、 創(chuàng)建Handler對象
    a) 與示例1不同的地方是,這里是通過匿名內(nèi)部類的方式來聲明的,而示例1是直接new出來的對象
    b) 重寫Handler對象的handlerMessage(Message msg)方法
    i. 這個(gè)方法傳入了一個(gè)Message對象,即消息對象,首先設(shè)置進(jìn)度條的進(jìn)度(這個(gè)值是Messag對象里面的一個(gè)成員變量arg1)。
    ii. 將要執(zhí)行的線程對象放入到隊(duì)列當(dāng)中
    6、 編寫B(tài)utton需要的監(jiān)聽器,并綁定
    a) 設(shè)置進(jìn)度條為顯示狀態(tài)
    b) 將要執(zhí)行的線程對象放入到隊(duì)列當(dāng)中
    下面是Activity的代碼:

    Java代碼 ?
  • package?android.handler;??
  • ??
  • import?android.app.Activity;??
  • import?android.os.Bundle;??
  • import?android.os.Handler;??
  • import?android.os.Message;??
  • import?android.view.View;??
  • import?android.view.View.OnClickListener;??
  • import?android.widget.Button;??
  • import?android.widget.ProgressBar;??
  • ??
  • public?class?ProgressBarHandlerTest?extends?Activity?{??
  • ????/**?Called?when?the?activity?is?first?created.?*/??
  • ??????
  • ????private?ProgressBar?progressBar;??
  • ????private?Button?startButton;??
  • ??????
  • ????@Override??
  • ????public?void?onCreate(Bundle?savedInstanceState)?{??
  • ????????super.onCreate(savedInstanceState);??
  • ????????setContentView(R.layout.main);??
  • ??????????
  • ????????progressBar?=?(ProgressBar)findViewById(R.id.progressbar);??
  • ????????startButton?=?(Button)findViewById(R.id.startButton);??
  • ??????????
  • ????????startButton.setOnClickListener(new?ProgressBarOnClickListener());??
  • ????}??
  • ??????
  • ????class?ProgressBarOnClickListener?implements?OnClickListener{??
  • ????????public?void?onClick(View?v)?{??
  • ????????????//設(shè)置進(jìn)度條為可見狀態(tài)??
  • ????????????progressBar.setVisibility(View.VISIBLE);??
  • ????????????updateBarHandler.post(updateThread);??
  • ????????}??
  • ????}??
  • ??????
  • ????//使用匿名內(nèi)部類來復(fù)寫Handler當(dāng)中的handlerMessage()方法??
  • ????Handler?updateBarHandler?=?new?Handler(){??
  • ????????@Override??
  • ????????public?void?handleMessage(Message?msg)?{??
  • ????????????progressBar.setProgress(msg.arg1);??
  • ????????????updateBarHandler.post(updateThread);????//將要執(zhí)行的線程放入到隊(duì)列當(dāng)中??
  • ????????}??
  • ????};??
  • ??????
  • ????//線程類,該類使用匿名內(nèi)部類的方式進(jìn)行聲明??
  • ????Runnable?updateThread?=?new?Runnable(){??
  • ????????int?i?=?0;??
  • ????????public?void?run()?{??
  • ????????????//?TODO?Auto-generated?method?stub??
  • ????????????System.out.println("Begin?Thread");??
  • ????????????i+=10;??
  • ????????????//得到一個(gè)消息對象,Message類是android系統(tǒng)提供的??
  • ????????????Message?msg?=?updateBarHandler.obtainMessage();??
  • ????????????//將Message對象的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ì)列當(dāng)中??
  • ????????????updateBarHandler.sendMessage(msg);??
  • ????????????//如果i的值等于100??
  • ????????????if?(i?==?100){??
  • ????????????????//將線程對象從隊(duì)列中移除??
  • ????????????????updateBarHandler.removeCallbacks(updateThread);???
  • ????????????}??
  • ????????}??
  • ????};??
  • }??

  • 項(xiàng)目源碼已經(jīng)上傳到附件了,有需要的可下載。

    不知道大家有沒有弄明白哈,我自己都寫得暈暈乎乎的了,沒辦法啊語文寫作能力不咋地,汗~



    這里其實(shí)有一點(diǎn)我沒有弄明白,就是當(dāng)進(jìn)度條的值等于100的時(shí)候,就將線程對象從隊(duì)列中移除,從而停止線程的運(yùn)行;這個(gè)在示例1中是沒有問題的, 當(dāng)點(diǎn)擊end按鈕,線程停止;但是在示例2例子中,當(dāng)進(jìn)度條的值等于100了,可是卻沒有停止,還是在繼續(xù)的運(yùn)行,每隔一秒就執(zhí)行一個(gè)線程,不知道這是為 什么,研究了好一會兒都沒弄明白,希望各位知道的可以跟我說說哈,咱們有機(jī)會多探討探討、多交流交流!

    ?

    評論

    16 樓 qiongqiong421122 2014-07-24?? 416849838 寫道 回答三樓? 不行,因?yàn)椴荒茉谧泳€程里更新UI
    updateThread里面的run方法是可以更新進(jìn)度條的,因?yàn)檫@里的操作相當(dāng)于在UI線程,只要稍微調(diào)整一下代碼,就可以做到三樓的要求。 15 樓 geniuz 2014-05-23?? 用Handler調(diào)用Runnable接口應(yīng)該並不是真的開新線程,只是實(shí)現(xiàn)接口而已,Handler把run擺進(jìn)UI線程的looper運(yùn)行的,所以即使不用消息,在run用應(yīng)該也能處理UI的東西。 14 樓 鯉魚味美 2014-04-24??
    ??????? public void run() {?
    ??????? if(i<=100){
    ??????????? // TODO Auto-generated method stub?
    ?????????? Log.i("QiHang","Begin Thread");?
    ??????????? i+=10;?
    ??????????? //得到一個(gè)消息對象,Message類是android系統(tǒng)提供的?
    ??????????? Message msg = updateBarHandler.obtainMessage();?
    ??????????? //將Message對象的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ì)列當(dāng)中?
    ??????????? updateBarHandler.sendMessage(msg);?
    ??????????? //如果i的值等于100?
    ?????????????
    ??????? }
    ??????? else{
    ??????? //將線程對象從隊(duì)列中移除?
    ??????????????? updateBarHandler.removeCallbacks(updateThread);
    ??????????????? Log.i("QiHang","End Thread");?
    ??????? }
    ??????? }


    這樣也可以結(jié)束 13 樓 xh194910 2014-02-27?? 樓主,我來啦 12 樓 yong7356 2013-08-30?? 學(xué)習(xí)了。。。。。 11 樓 yong7356 2013-08-02?? 。。。。。。。。。。。。。。。。。。。。 10 樓 mengrenfeixiang 2012-12-08?? 例2會導(dǎo)致updateThread的run方法死循環(huán),原因如下:
    當(dāng)i==100時(shí),執(zhí)行了下面幾行代碼
    if (i == 100){?
    ??????????????? //將線程對象從隊(duì)列中移除?
    ??????????????? updateBarHandler.removeCallbacks(updateThread);??
    ??? }
    看似updateThread線程從線程對象隊(duì)列中移除,不會再執(zhí)行了,但是執(zhí)行這幾行代碼前執(zhí)行了下面代碼
    //將Message對象加入到消息隊(duì)列當(dāng)中?
    updateBarHandler.sendMessage(msg);
    這會導(dǎo)致下面的代碼被執(zhí)行
    public void handleMessage(Message msg) {????
    ??????????? progressBar.setProgress(msg.arg1);????
    ?????????? updateBarHandler.post(updateThread);??? //將要執(zhí)行的線程放入到隊(duì)列當(dāng)中????
    }
    updateThread線程又加到線程對象隊(duì)列中,updateThread線程永遠(yuǎn)不會從線程對象隊(duì)列中移除,updateThread的run方法不斷的執(zhí)行,這就導(dǎo)致了死循環(huán)。

    解決方案:
    將 updateThread的run方法里的
    if (i == 100){?
    ??????????????? //將線程對象從隊(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)中
    ??????????? }?
    ??????? }?
    ??? };?

    我是通過調(diào)試查看代碼的執(zhí)行順序,發(fā)現(xiàn)這個(gè)問題的 9 樓 jkzhao 2012-10-27?? Handler主要是用于子線程與主線程的通訊,子線程可以把消息發(fā)送到主線程的Looper,有主線程來處理。 8 樓 tracydeerge 2012-10-25?? 我覺得Handler大多用來作為線程池中的線程與主線程的通信工具! 7 樓 416849838 2011-11-25?? 回答三樓? 不行,因?yàn)椴荒茉谧泳€程里更新UI 6 樓 zhangjm123 2011-11-20?? 將 //如果i的值等于100?
    ??????????? if (i == 100){?
    ??????????????? //將線程對象從隊(duì)列中移除?
    ??????????????? updateBarHandler.removeCallbacks(updateThread);??
    ??????????? }?
    刪了,寫到如5樓寫的那樣就行了!! 5 樓 sserf 2011-09-28?? 不錯,很全面,轉(zhuǎn)了! 4 樓 cj83226 2011-09-05?? Java代碼 ?
  • if(msg.arg1>=progressBar.getMax())???
  • ????????????{????
  • ????????????????System.out.println("removeCallbacks");??
  • ????????????????updateBarHandler.removeCallbacks(updateThread);????????
  • ????????????????
  • ????????????}??
  • ????????????else?{????
  • ????????????????System.out.println("updateBarHandler.post");??
  • ????????????????updateBarHandler.post(updateThread);????//將要執(zhí)行的線程放入到隊(duì)列當(dāng)中??
  • ????????????}??

  • 應(yīng)該是這樣吧。。。。 3 樓 wjb_forward 2011-03-24?? 請問直接在run方法里面增加進(jìn)度條的進(jìn)度不行嗎,把i寫成一個(gè)全局變量。 2 樓 meng_fan_zhen 2011-03-16?? hehez 寫道 Java代碼 ?
  • //使用匿名內(nèi)部類來復(fù)寫Handler當(dāng)中的handlerMessage()方法?????
  • ????Handler?updateBarHandler?=?new?Handler(){?????
  • ????????@Override????
  • ????????public?void?handleMessage(Message?msg)?{?????
  • ????????????progressBar.setProgress(msg.arg1);????
  • ?if(msg.arg1<=progressBar.getMax())?{??
  • updateBarHandler.removeCallbacks(updateThread);??????
  • ??
  • ???????????}else?{??
  • updateBarHandler.post(updateThread);????//將要執(zhí)行的線程放入到隊(duì)列當(dāng)中?????
  • ??
  • }??
  • ????????}?????
  • ???};??



  • 我試了下,這個(gè)是好使的。

    1樓的判斷條件是不是正好寫反了? 1 樓 hehez 2011-03-04?? Java代碼 ?
  • if?(i?==?100){?????
  • ????????????????//將線程對象從隊(duì)列中移除?????
  • ???????????????updateBarHandler.removeCallbacks(updateThread);??????
  • ????????????}?????


  • 就這段,我也出現(xiàn)和你一樣的狀況。我在網(wǎng)上搜了好多,有人說是,removeCallbacks只是把updateThread這個(gè)線程從隊(duì)列中移除,但是并沒有停止線程。
    然后網(wǎng)上也有人提供了一個(gè)修正方法,就是在下面這段代碼中間

    Java代碼 ?
  • //使用匿名內(nèi)部類來復(fù)寫Handler當(dāng)中的handlerMessage()方法?????
  • ????Handler?updateBarHandler?=?new?Handler(){?????
  • ????????@Override????
  • ????????public?void?handleMessage(Message?msg)?{?????
  • ????????????progressBar.setProgress(msg.arg1);?????
  • ???????????updateBarHandler.post(updateThread);????//將要執(zhí)行的線程放入到隊(duì)列當(dāng)中?????
  • ????????}?????
  • ???};??


  • 添加一個(gè)判斷

    Java代碼 ?
  • //使用匿名內(nèi)部類來復(fù)寫Handler當(dāng)中的handlerMessage()方法?????
  • ????Handler?updateBarHandler?=?new?Handler(){?????
  • ????????@Override????
  • ????????public?void?handleMessage(Message?msg)?{?????
  • ????????????progressBar.setProgress(msg.arg1);????
  • ?if(msg.arg1<=progressBar.getMax())?{??
  • updateBarHandler.removeCallbacks(updateThread);??????
  • ??
  • ???????????}else?{??
  • updateBarHandler.post(updateThread);????//將要執(zhí)行的線程放入到隊(duì)列當(dāng)中?????
  • ??
  • }??
  • ????????}?????
  • ???};??



  • 我試了下,這個(gè)是好使的。

    轉(zhuǎn)載于:https://www.cnblogs.com/xgjblog/p/3881470.html

    總結(jié)

    以上是生活随笔為你收集整理的android Handler的使用(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。