Android學習筆記--Handler用法總結

不錯的例子:http://www.cnblogs.com/menlsh/archive/2013/06/07/3125341.htmlhtml

轉自:一葉知秋的博客 http://blog.sina.com.cn/s/blog_77c6324101016jp8.html多線程

1、Handler的定義:
  Handler主要接收子線程發送的數據, 並用此數據配合主線程更新UI,用來跟UI主線程交互用。好比
  (1) 能夠用handler發送一個message,而後在handler的線程中來接收、處理該消息,以免直接在UI主線程中處理事務致使影響UI主線程的其餘處理工做,Android提供了Handler做爲主線程和子線程的紐帶;
  (2) 也能夠將handler對象傳給其餘進程,以便在其餘進程中經過handler給你發送事件
  (3) 還能夠經過handler的延時發送message,能夠延時處理一些事務的處理ide

  一般狀況下,當應用程序啓動時,Android首先會開啓一個主線程 (也就是UI線程) , 主線程爲管理界面中的UI控件,進行事件分發。若是此時須要一個耗時的操做,例如:聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操做放在主線程中,若是你放在主線程中的話,界面會出現假死現象,若是5秒鐘尚未完成的話,會收到Android系統的一個錯誤提示"強制關閉"。
  這個時候咱們須要把這些耗時的操做,放在一個子線程中,由於子線程涉及到UI更新,可是當子線程中有涉及到操做UI的操做時,就會對主線程產生危險,也就是說,更新UI只能在主線程中更新,在子線程中操做是危險的. 這個時候,Handler就出現了來解決這個複雜的問題,因爲Handler運行在主線程中(UI線程中),它與子線程能夠經過Message對象來傳遞數據,這個時候,Handler就承擔着接受子線程傳過來的(子線程用sedMessage()方法傳遞)Message對象,(裏面包含數據), 把這些消息放入主線程隊列中,配合主線程進行更新UI。

2、Handler一些特色
  handler能夠分發Message對象和Runnable對象到主線程中, 每一個Handler實例,都會綁定到建立他的線程中(通常是位於主線程), 也就是說Handler對象初始化後,就默認與對它初始化的進程的消息隊列綁定,所以能夠利用Handler所包含的消息隊列,制定一些操做的順序。

3、Handler中分發消息的一些方法
  post(Runnable)
  postAtTime(Runnable,long)
  postDelayed(Runnable long)
    post類方法容許你排列一個Runnable對象到主線程隊列中
  sendEmptyMessage(int)
  sendMessage(Message)
  sendMessageAtTime(Message,long)
  sendMessageDelayed(Message,long)
    sendMessage類方法, 容許你安排一個帶數據的Message對象到隊列中,等待更新.

4、應用實例:
1. 傳遞Message。用於接受子線程發送的數據, 並用此數據配合主線程更新UI。
  在Android中,對於UI的操做一般須要放在主線程中進行操做。若是在子線程中有關於UI的操做,那麼就須要把數據消息做爲一個Message對象發送到消息隊列中,而後,用Handler中的handlerMessge方法處理傳過來的數據信息,並操做UI。類sendMessage(Message msg)方法實現發送消息的操做。 在初始化Handler對象時重寫的handleMessage方法來接收Messgae並進行相關操做。
2. 傳遞Runnable對象。用於經過Handler綁定的消息隊列,安排不一樣操做的執行順序。
  Handler對象在進行初始化的時候,會默認的自動綁定消息隊列。利用類post方法,能夠將Runnable對象發送到消息隊列中,按照隊列的機制按順序執行不一樣的Runnable對象中的run方法。
  另外,Android的CPU分配的最小單元是線程,Handler通常是在某個線程裏建立的,於是Handler和Thread就是相互綁定的,一一對應。而Runnable是一個接口,Thread是Runnable的子類。因此說,他倆都算一個進程。oop

public class HandlerActivity extends Activity {
    // 聲明兩個按鈕控件
    private Button startButton = null;
    private Button endButton = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 根據控件的ID獲得表明控件的對象,併爲這兩個按鈕設置相應的監聽器
        startButton = (Button) findViewById(R.id.startButton);
        startButton.setOnClickListener(new StartButtonListener());
        endButton = (Button) findViewById(R.id.endButton);
        endButton.setOnClickListener(new EndButtonListener());
    }

    class StartButtonListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            // 調用Handler的post方法,將要執行的線程對象添加到隊列當中
            handler.post(updateThread);
        }
    }

    class EndButtonListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            handler.removeCallbacks(updateThread);
        }
    }

    // 建立一個Handler對象
    Handler handler = new Handler();
    // 將要執行的操做寫在線程對象的run方法當中
    Runnable updateThread = new Runnable() {
        @Override
        public void run() {
            System.out.println("UpdateThread");
            // 在run方法內部,執行postDelayed或者是post方法
            handler.postDelayed(updateThread, 3000);
        }
    };
}

   程序的運行結果就是每隔3秒鐘,就會在控制檯打印一行UpdateTread。這是由於實現了Runnable接口的updateThread對象進入了空的消息隊列即被當即執行run方法,而在run方法的內部,又在3000ms以後將其再次發送進入消息隊列中。post

3.  Handler和多線程
post方法雖然發送的是一個實現了Runnable接口的類對象,可是它並不是建立了一個新線程,而是執行了該對象中的run方法。也就是說,整個run中的操做和主線程處於同一個線程。(驗證:http://blog.sina.com.cn/s/blog_78c913e30100uqmf.html
  這樣對於那些簡單的操做,彷佛並不會影響。可是對於耗時較長的操做,就會出現「假死」。爲了解決這個問題,就須要使得handler綁定到一個新開啓線程的消息隊列上,在這個處於另外線程的上的消息隊列中處理傳過來的Runnable對象和消息。spa

public class HandlerTest2 extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 打印了當前線程的ID
        System.out.println("Activity-->" + Thread.currentThread().getId());
        // 生成一個HandlerThread對象
        HandlerThread handlerThread = new HandlerThread("handler_thread");
        // 在使用HandlerThread的getLooper()方法以前,必須先調用該類的start(),同時開啓一個新線程;
        handlerThread.start();
        // 將由HandlerThread獲取的Looper傳遞給Handler對象,即由處於另外線程的Looper代替handler初始化時默認綁定的消息隊列來處理消息。
        // HandlerThread顧名思義就是能夠處理消息循環的線程,它是一個擁有Looper的線程,能夠處理消息循環;
        // 其實與其說Handler和一個線程綁定,倒不如說Handler和Looper是一一對應的。
        MyHandler myHandler = new MyHandler(handlerThread.getLooper());
        Message msg = myHandler.obtainMessage();
        // 將msg發送到目標對象,所謂的目標對象,就是生成該msg對象的handler對象
        Bundle b = new Bundle();
        b.putInt("age", 20);
        b.putString("name", "Jhon");
        msg.setData(b);
        msg.sendToTarget(); // 將msg發送到myHandler
    }

    // 定義類
    class MyHandler extends Handler {
        public MyHandler() {
        }

        public MyHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            Bundle b = msg.getData();
            int age = b.getInt("age");
            String name = b.getString("name");
            System.out.println("age is " + age + ", name is" + name);
            System.out.println("Handler--->" + Thread.currentThread().getId());
            System.out.println("handlerMessage");
        }
    }
}

  這樣,當使用sendMessage方法傳遞消息或者使用post方法傳遞Runnable對象時,就會把它們傳遞到與handler對象綁定的處於另一個線程的消息隊列中,它們將在另外的消息隊列中被處理。而主線程還會在發送操做完成時候繼續進行,不會影響當前的操做。
  這裏須要注意,這裏用到的多線程並不是由Runnable對象開啓的,而是ThreadHandler對象開啓的。Runnable對象只是做爲一個封裝了操做的對象被傳遞,並未產生新線程。.net

另外再強調一遍,在UI線程(主線程)中:線程

mHandler=new Handler();
mHandler.post(new Runnable(){
    void run(){
        //執行代碼..
    }
});

這個線程實際上是在UI線程以內運行的,並無新建線程。

常見的新建線程的方法是:code

Thread thread = new Thread();
thread.start();

HandlerThread thread = new HandlerThread("string");
thread.start();

 

注意:::::http://blog.csdn.net/catherine880619/article/details/6719707htm

 

Message msg = handler.obtainMessage();
                        msg.arg1 = i;
                        msg.sendToTarget(); 

 

Message msg=new Message();
    msg.arg1=i;
    handler.sendMessage(msg);

 

 

相關資料:http://www.cnblogs.com/playing/archive/2011/03/24/1993583.html

相關文章
相關標籤/搜索