首頁 收藏 QQ群
 網(wǎng)站導(dǎo)航

ZNDS智能電視網(wǎng) 推薦當(dāng)貝市場

TV應(yīng)用下載 / 資源分享區(qū)

軟件下載 | 游戲 | 討論 | 電視計(jì)算器

綜合交流 / 評測 / 活動區(qū)

交流區(qū) | 測硬件 | 網(wǎng)站活動 | Z幣中心

新手入門 / 進(jìn)階 / 社區(qū)互助

新手 | 你問我答 | 免費(fèi)刷機(jī)救磚 | ROM固件

查看: 13694|回復(fù): 0
上一主題 下一主題
[案例]

android的handler機(jī)制

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2013-8-28 16:29 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
7
Handler可以發(fā)送Messsage和Runnable對象到與其相關(guān)聯(lián)的線程的消息隊(duì)列。每個(gè)Handler對象與創(chuàng)建它的線程相關(guān)聯(lián),并且每個(gè)Handler對象只能與一個(gè)線程相關(guān)聯(lián)。
Handler一般有兩種用途:1)執(zhí)行計(jì)劃任務(wù),你可以再預(yù)定的實(shí)現(xiàn)執(zhí)行某些任務(wù),可以模擬定時(shí)器。2)線程間通信。在Android的應(yīng)用啟動時(shí),會 創(chuàng)建一個(gè)主線程,主線程會創(chuàng)建一個(gè)消息隊(duì)列來處理各種消息。當(dāng)你創(chuàng)建子線程時(shí),你可以在你的子線程中拿到父線程中創(chuàng)建的Handler對象,就可以通過該 對象向父線程的消息隊(duì)列發(fā)送消息了。由于Android要求在UI線程中更新界面,因此,可以通過該方法在其它線程中更新界面。   
◆ 通過Runnable在子線程中更新界面的例子
1.○ 在onCreate中創(chuàng)建Handler   
public class HandlerTestApp extends Activity {   
        Handler mHandler;   
        TextView mText;   
        /** Called when the activity is first created. */   
       @Override   
       public void onCreate(Bundle savedInstanceState) {   
           super.onCreate(savedInstanceState);   
           setContentView(R.layout.main);   
           mHandler = new Handler();//
創(chuàng)建Handler   
           mText = (TextView) findViewById(R.id.text0);//
一個(gè)TextView   
       }   
     
○ 構(gòu)建Runnable對象,在runnable中更新界面,此處,我們修改了TextView的文字.此處需要說明的是,Runnable對象可以再主線程中創(chuàng)建,也可以再子線程中創(chuàng)建。我們此處是在子線程中創(chuàng)建的。     
     Runnable mRunnable0 = new Runnable()   
    {   
                @Override   
                public void run() {   
                        mText.setText("This is Update from ohter thread, Mouse DOWN");   
                }   
    };   
?   
○ 創(chuàng)建子線程,在線程的run函數(shù)中,我們向主線程的消息隊(duì)列發(fā)送了一個(gè)runnable來更新界面。
    private void updateUIByRunnable(){   
          new Thread()     
         {     
               //Message msg = mHandler.obtainMessage();     
              public void run()     
             {
                   //mText.setText("This is Update from ohter thread, Mouse DOWN");//這句將拋出異常   
                   mHandler.post(mRunnable0);     
             }     
         }.start();
     }
用Message在子線程中來更新界面
1.    用Message更新界面與Runnable更新界面類似,只是需要修改幾個(gè)地方。   
    實(shí)現(xiàn)自己的Handler,對消息進(jìn)行處理
    private class MyHandler extends Handler   
    {
        @Override   
        public void handleMessage(Message msg) {   
            super.handleMessage(msg);   
            switch(msg.what)   
            {   
            case UPDATE ://
在收到消息時(shí),對界面進(jìn)行更新   
                mText.setText("This update by message");   
                break;   
            }   
        }   
    }
    ○ 在新的線程中發(fā)送消息        
    private void updateByMessage()   
    {   
        //
匿名對象   
         new Thread()   
         {   
                public void run()   
                {   
                    //mText.setText("This is Update from ohter thread, Mouse DOWN");
                    //UPDATE是一個(gè)自己定義的整數(shù),代表了消息ID   
                    Message msg = mHandler.obtainMessage(UPDATE);   
                    mHandler.sendMessage(msg);   
                }   
         }.start();   
    }
AsyncTask與handler
AsyncTask實(shí)際上就是一個(gè)線程池,AsyncTask在代碼上比handler要輕量級別,而實(shí)際上要比handler更耗資源,因?yàn)锳syncTask底層是一個(gè)線程池!而Handler僅僅就是發(fā)送了一個(gè)消息隊(duì)列,連線程都沒有開。   
但是,如果異步任務(wù)的數(shù)據(jù)特別龐大,AsyncTask這種線程池結(jié)構(gòu)的優(yōu)勢就體現(xiàn)出來了。
android的ui線程操作并不是安全的,并且和用戶直接進(jìn)行界面交互的操作都必須在ui線程中進(jìn)行才可以。這種模式叫做單線程模式。
我們在單線程模式下編程一定要注意:不要阻塞ui線程、確保只在ui線程中訪問ui組件
當(dāng)我們要執(zhí)行一個(gè)復(fù)雜耗時(shí)的算法并且最終要將計(jì)算結(jié)果反映到ui上時(shí),我們會發(fā)現(xiàn),我們根本沒辦法同時(shí)保證上面的兩點(diǎn)要求;我們肯定會想到開啟一個(gè)新的線程,讓這個(gè)復(fù)雜耗時(shí)的任務(wù)到后臺去執(zhí)行,但是執(zhí)行完畢了呢?我們發(fā)現(xiàn),我們無法再與ui進(jìn)行交互了。
為了解決這種情況,android為我們提供了很多辦法。
1)、handler和message機(jī)制:通過顯示的拋出、捕獲消息與ui進(jìn)行交互;
2)、Activity.runOnUiThread(Runnable):如果當(dāng)前線程為ui線程,則立即執(zhí)行;否則,將參數(shù)中的線程操作放入到ui線程的事件隊(duì)列中,等待執(zhí)行。
3)、View.post(Runnable):將操作放入到message隊(duì)列中,如果放入成功,該操作將會在ui線程中執(zhí)行,并返回true,否則返回false
4)、View.postDelayed(Runnable, long)跟第三條基本一樣,只不過添加了一個(gè)延遲時(shí)間。
5)、android1.5以后為我們提供了一個(gè)工具類來搞定這個(gè)問題AsyncTask.
AsyncTask是抽象類,定義了三種泛型類型 Params,Progress,Result。
Params 啟動任務(wù)執(zhí)行的輸入?yún)?shù),比如HTTP請求的URL
Progress 后臺任務(wù)執(zhí)行的百分比。
Result 后臺執(zhí)行任務(wù)最終返回的結(jié)果,比如String
用程序調(diào)用,開發(fā)者需要做的就是實(shí)現(xiàn)這些方法。
1) 子類化AsyncTask
2) 實(shí)現(xiàn)AsyncTask中定義的下面一個(gè)或幾個(gè)方法
,該方法將在執(zhí)行實(shí)際的后臺操作前被UI thread調(diào)用。可以在該方法中做一些準(zhǔn)備工作,如在界面上顯示一個(gè)進(jìn)度條。
,將在onPreExecute 方法執(zhí)行后馬上執(zhí)行,該方法運(yùn)行在后臺線程中。這里將主要負(fù)責(zé)執(zhí)行那些很耗時(shí)的后臺計(jì)算工作??梢哉{(diào)用 publishProgress方法來更新實(shí)時(shí)的任務(wù)進(jìn)度。該方法是抽象方法,子類必須實(shí)現(xiàn)。
,在publishProgress方法被調(diào)用后,UI thread將調(diào)用這個(gè)方法從而在界面上展示任務(wù)的進(jìn)展情況,例如通過一個(gè)進(jìn)度條進(jìn)行展示。
,在doInBackground 執(zhí)行完成后,onPostExecute 方法將被UI thread調(diào)用,后臺的計(jì)算結(jié)果將通過該方法傳遞到UI thread.
為了正確的使用AsyncTask類,以下是幾條必須遵守的準(zhǔn)則:
1) Task的實(shí)例必須在UI thread中創(chuàng)建
2) execute方法必須在UI thread中調(diào)用
3) 不要手動的調(diào)用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)這幾個(gè)方法
4) 該task只能被執(zhí)行一次,否則多次調(diào)用時(shí)將會出現(xiàn)異常</div

上一篇:感覺學(xué)習(xí)android需要溫故知新
下一篇:第27講:Handler使用入門.docx
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

Archiver|新帖|標(biāo)簽|軟件|Sitemap|ZNDS智能電視網(wǎng) ( 蘇ICP備2023012627號 )

網(wǎng)絡(luò)信息服務(wù)信用承諾書 | 增值電信業(yè)務(wù)經(jīng)營許可證:蘇B2-20221768 丨 蘇公網(wǎng)安備 32011402011373號

GMT+8, 2025-2-3 00:57 , Processed in 0.096064 second(s), 13 queries , Redis On.

Powered by Discuz!

監(jiān)督舉報(bào):report#znds.com (請將#替換為@)

© 2007-2025 ZNDS.Com

快速回復(fù) 返回頂部 返回列表