天天看點

Android Handler Message Looper

Handler機制作用

handler是android中專門用來線上程之間傳遞資訊類的工具。

當應用程式啟動時,會開啟一個主線程(也就是UI線程),由它來管理UI,監聽使用者點選,來響應使用者并分發事件等。是以一般在主線程中不要執行比較耗時的操作,如聯網下載下傳資料等,否則出現ANR錯誤。是以就将這些操作放在子線程中,但是由于AndroidUI線程是不安全的,是以隻能在主線程中更新UI。Handler就是用來 子線程和建立Handler的線程進行通信的。

消息的處理者,handler負責将需要傳遞的資訊封裝成Message,通過調用handler對象的obtainMessage()來實作;将消息傳遞給Looper,這是通過handler對象的sendMessage()來實作的。繼而由Looper将Message放入MessageQueue中。當Looper對象看到MessageQueue中含有Message,就将其廣播出去。該handler對象收到該消息後,調用相應的handler對象的handleMessage()方法

Looper

主要功能是為特定單一線程運作一個消息環。一個線程對應一個looper。同樣一個looper對應一個線程。這就是所謂的特定單一。一般情況下,在一個線程建立時他本身是不會生産他特定單一的looper的(主線程是個特例)。是以我們需要手動的把一個looper與線程相關聯。其方法隻需在需要關聯的looper的線程中調用Looper.prepare。之後我們再調用Looper.loop啟動looper。

從代碼層面來講Looper是MessageQueue的管理者。每一個MessageQueue都不能脫離Looper而存在,Looper對象的建立是通過prepare函數來實作的。同時每一個Looper對象

和一個線程關聯。通過調用Looper.myLooper()可以獲得目前線程的Looper對象

建立一個Looper對象時,會同時建立一個MessageQueue對象。除了主線程有預設的Looper,其他線程預設是沒有MessageQueue對象的,是以,不能

接受Message。如需要接受,自己定義一個Looper對象(通過prepare函數),這樣該線程就有了自己的Looper對象和MessageQueue資料結構了。

Looper從MessageQueue中取出Message然後,交由Handler的handleMessage進行處理。處理完成後,調用Message.recycle()将其放入Message Pool中。

class MyThread extends Thread{

        public void run(){
            Looper.prepare(); //建立該線程的Looper對象,用于接收消息
            //這裡Looper.myLooper()獲得的就是該線程的Looper對象了
            handler = new ThreadHandler(Looper.myLooper());

            //不經常去看看,你怎麼知道你有新消息呢?
            Looper.loop(); 

        }
           

MessageQueue

MessageQueue:是一種資料結構,見名知義,就是一個消息隊列,存放消息的地方。每一個線程最多隻可以擁有一個MessageQueue資料結構。建立一個線程的時候,并不會自動建立其MessageQueue。通常使用一個Looper對象對該線程的MessageQueue進行管理。主線程建立時,會建立一個預設的Looper對象,而Looper對象的建立,将自動建立一個Message Queue。其他非主線程,不會自動建立Looper,要需要的時候,通過調用prepare函數來實作。

Message

Message:消息對象,Message Queue中的存放的對象。一個Message Queue中包含多個Message。Message執行個體對象的取得,通常使用Message類裡的靜态方法obtain(),該方法有多個重載版本可供選擇;它的建立并不一定是直接建立一個新的執行個體,而是先從Message Pool(消息池)中看有沒有可用的Message執行個體,存在則直接取出傳回這個執行個體。如果Message Pool中沒有可用的Message執行個體,則才用給定的參數建立一個Message對象。調用removeMessages()時,将Message從Message Queue中删除,同時放入到Message Pool中。除了上面這種方式,也可以通過Handler對象的obtainMessage()擷取一個Message執行個體。

代碼示例:

主線程給自己發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest =(Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);

        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {

                Looper looper = Looper.getMainLooper(); //主線程的Looper對象
                //這裡以主線程的Looper對象建立了handler,
                //是以,這個handler發送的Message會被傳遞給主線程的MessageQueue。
                handler = new MyHandler(looper);
                handler.removeMessages();
                //建構Message對象
                //第一個參數:是自己指定的message代号,友善在handler選擇性地接收
                //第二三個參數沒有什麼意義
                //第四個參數需要封裝的對象
                Message msg = handler.obtainMessage(,,,"主線程發消息了");

                handler.sendMessage(msg); //發送消息

            }
        });
    }

    class MyHandler extends Handler{

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

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
        }
    }
}
           

其他線程給主線程發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);

        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {

                //可以看出這裡啟動了一個線程來操作消息的封裝和發送的工作
                //這樣原來主線程的發送就變成了其他線程的發送,簡單吧?呵呵
                new MyThread().start();    
            }
        });
    }

    class MyHandler extends Handler{

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

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
        }
    }

    //加了一個線程類
    class MyThread extends Thread{

        public void run(){
            Looper looper = Looper.getMainLooper(); //主線程的Looper對象
            //這裡以主線程的Looper對象建立了handler,
            //是以,這個handler發送的Message會被傳遞給主線程的MessageQueue。
            handler = new MyHandler(looper);

            //建構Message對象
            //第一個參數:是自己指定的message代号,友善在handler選擇性地接收
            //第二三個參數沒有什麼意義
            //第四個參數需要封裝的對象
            Message msg = handler.obtainMessage(,,,"其他線程發消息了");

            handler.sendMessage(msg); //發送消息            
        }
    }
}
           

主線程給其他線程發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);


        //啟動線程
        new MyThread().start();    

        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                //這裡handler的執行個體化線上程中
                //線程啟動的時候就已經執行個體化了
                Message msg = handler.obtainMessage(,,,"主線程發送的消息");
                handler.sendMessage(msg);
            }
        });
    }

    class MyHandler extends Handler{

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

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
        }
    }

    class MyThread extends Thread{

        public void run(){
            Looper.prepare(); //建立該線程的Looper對象,用于接收消息

            //注意了:這裡的handler是定義在主線程中的哦,呵呵,
            //前面看到直接使用了handler對象,是不是在找,在什麼地方執行個體化的呢?
            //現在看到了吧???呵呵,開始的時候執行個體化不了,因為該線程的Looper對象
            //還不存在呢。現在可以執行個體化了
            //這裡Looper.myLooper()獲得的就是該線程的Looper對象了
            handler = new ThreadHandler(Looper.myLooper());

            //這個方法,有疑惑嗎?
            //其實就是一個循環,循環從MessageQueue中取消息。
            //不經常去看看,你怎麼知道你有新消息呢???
            Looper.loop(); 

        }

        //定義線程類中的消息處理類
        class ThreadHandler extends Handler{

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

            public void handleMessage(Message msg){
                //這裡對該線程中的MessageQueue中的Message進行處理
                //這裡我們再傳回給主線程一個消息
                handler = new MyHandler(Looper.getMainLooper());

                Message msg2 = handler.obtainMessage(,,,"子線程收到:"+(String)msg.obj);

                handler.sendMessage(msg2);
            }
        }
    }
}