Message,MessageQueue,Looper,Handler详解+实例
Message,MessageQueue,Looper,Handler詳解+實(shí)例
原文地址
Android的Handler使用(這篇簡(jiǎn)單介紹Handler的使用)
一、幾個(gè)關(guān)鍵概念
1、MessageQueue:是一種數(shù)據(jù)結(jié)構(gòu),見(jiàn)名知義,就是一個(gè)消息隊(duì)列,存放消息的地方。每一個(gè)線程最多只可以擁有一個(gè)MessageQueue數(shù)據(jù)結(jié)構(gòu)。
創(chuàng)建一個(gè)線程的時(shí)候,并不會(huì)自動(dòng)創(chuàng)建其MessageQueue。通常使用一個(gè)Looper對(duì)象對(duì)該線程的MessageQueue進(jìn)行管理。主線程創(chuàng)建時(shí),會(huì)創(chuàng)建一
個(gè)默認(rèn)的Looper對(duì)象,而Looper對(duì)象的創(chuàng)建,將自動(dòng)創(chuàng)建一個(gè)Message Queue。其他非主線程,不會(huì)自動(dòng)創(chuàng)建Looper,要需要的時(shí)候,通過(guò)調(diào)
用prepare函數(shù)來(lái)實(shí)現(xiàn)。
2、Message:消息對(duì)象,Message Queue中的存放的對(duì)象。一個(gè)Message Queue中包含多個(gè)Message。
Message實(shí)例對(duì)象的取得,通常使用Message類(lèi)里的靜態(tài)方法obtain(),該方法有多個(gè)重載版本可供選擇;它的創(chuàng)建并不一定是直接創(chuàng)建一個(gè)新的實(shí)例,
而是先從Message Pool(消息池)中看有沒(méi)有可用的Message實(shí)例,存在則直接取出返回這個(gè)實(shí)例。如果Message Pool中沒(méi)有可用的Message實(shí)例,
則才用給定的參數(shù)創(chuàng)建一個(gè)Message對(duì)象。調(diào)用removeMessages()時(shí),將Message從Message Queue中刪除,同時(shí)放入到Message Pool中。除了上面這
種方式,也可以通過(guò)Handler對(duì)象的obtainMessage()獲取一個(gè)Message實(shí)例。
3、Looper:
是MessageQueue的管理者。每一個(gè)MessageQueue都不能脫離Looper而存在,Looper對(duì)象的創(chuàng)建是通過(guò)prepare函數(shù)來(lái)實(shí)現(xiàn)的。同時(shí)每一個(gè)Looper對(duì)象
和一個(gè)線程關(guān)聯(lián)。通過(guò)調(diào)用Looper.myLooper()可以獲得當(dāng)前線程的Looper對(duì)象
創(chuàng)建一個(gè)Looper對(duì)象時(shí),會(huì)同時(shí)創(chuàng)建一個(gè)MessageQueue對(duì)象。除了主線程有默認(rèn)的Looper,其他線程默認(rèn)是沒(méi)有MessageQueue對(duì)象的,所以,不能
接受Message。如需要接受,自己定義一個(gè)Looper對(duì)象(通過(guò)prepare函數(shù)),這樣該線程就有了自己的Looper對(duì)象和MessageQueue數(shù)據(jù)結(jié)構(gòu)了。
Looper從MessageQueue中取出Message然后,交由Handler的handleMessage進(jìn)行處理。處理完成后,調(diào)用Message.recycle()將其放入Message Pool中。
4、Handler:
消息的處理者,handler負(fù)責(zé)將需要傳遞的信息封裝成Message,通過(guò)調(diào)用handler對(duì)象的obtainMessage()來(lái)實(shí)現(xiàn);
將消息傳遞給Looper,這是通過(guò)handler對(duì)象的sendMessage()來(lái)實(shí)現(xiàn)的。繼而由Looper將Message放入MessageQueue中。
當(dāng)Looper對(duì)象看到MessageQueue中含有Message,就將其廣播出去。該handler對(duì)象收到該消息后,調(diào)用相應(yīng)的handler對(duì)象的handleMessage()方法
對(duì)其進(jìn)行處理。
二、線程之間的消息如何進(jìn)行傳遞
1、主線程給自己發(fā)送Message
package test.message;
import?android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
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對(duì)象
??????????????? //這里以主線程的Looper對(duì)象創(chuàng)建了handler,
??????????????? //所以,這個(gè)handler發(fā)送的Message會(huì)被傳遞給主線程的MessageQueue。
??????????????? handler = new MyHandler(looper);
??????????????? handler.removeMessages(0);
??????????????? //構(gòu)建Message對(duì)象
??????????????? //第一個(gè)參數(shù):是自己指定的message代號(hào),方便在handler選擇性地接收
??????????????? //第二三個(gè)參數(shù)沒(méi)有什么意義
??????????????? //第四個(gè)參數(shù)需要封裝的對(duì)象
??????????????? Message msg = handler.obtainMessage(1,1,1,"主線程發(fā)消息了");
????????????????
??????????????? handler.sendMessage(msg); //發(fā)送消息
????????????????
??????????? }
??????? });
??? }
????
??? class MyHandler extends Handler{
????????
??????? public MyHandler(Looper looper){
??????????? super(looper);
??????? }
????????
??????? public void handleMessage(Message msg){
??????????? super.handleMessage(msg);
??????????? textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
??????? }
??? }
}
2、其他線程給主線程發(fā)送Message
package test.message;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
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) {
????????????????
??????????????? //可以看出這里啟動(dòng)了一個(gè)線程來(lái)操作消息的封裝和發(fā)送的工作
??????????????? //這樣原來(lái)主線程的發(fā)送就變成了其他線程的發(fā)送,簡(jiǎn)單吧?呵呵
??????????????? 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);
??????? }
??? }
????
??? //加了一個(gè)線程類(lèi)
??? class MyThread extends Thread{
????????
??????? public void run(){
??????????? Looper looper = Looper.getMainLooper(); //主線程的Looper對(duì)象
??????????? //這里以主線程的Looper對(duì)象創(chuàng)建了handler,
??????????? //所以,這個(gè)handler發(fā)送的Message會(huì)被傳遞給主線程的MessageQueue。
??????????? handler = new MyHandler(looper);
??????????? //構(gòu)建Message對(duì)象
??????????? //第一個(gè)參數(shù):是自己指定的message代號(hào),方便在handler選擇性地接收
??????????? //第二三個(gè)參數(shù)沒(méi)有什么意義
??????????? //第四個(gè)參數(shù)需要封裝的對(duì)象
??????????? Message msg = handler.obtainMessage(1,1,1,"其他線程發(fā)消息了");
????????????
??????????? handler.sendMessage(msg); //發(fā)送消息????????????
??????? }
??? }
}
3、主線程給其他線程發(fā)送Message
package test.message;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
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);
????????
????????
??????? //啟動(dòng)線程
??????? new MyThread().start();????
????????
??????? btnTest.setOnClickListener(new View.OnClickListener() {
????????????
??????????? @Override
??????????? public void onClick(View arg0) {
??????????????? //這里handler的實(shí)例化在線程中
??????????????? //線程啟動(dòng)的時(shí)候就已經(jīng)實(shí)例化了
??????????????? Message msg = handler.obtainMessage(1,1,1,"主線程發(fā)送的消息");
??????????????? 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(); //創(chuàng)建該線程的Looper對(duì)象,用于接收消息
????????????
??????????? //注意了:這里的handler是定義在主線程中的哦,呵呵,
??????????? //前面看到直接使用了handler對(duì)象,是不是在找,在什么地方實(shí)例化的呢?
??????????? //現(xiàn)在看到了吧???呵呵,開(kāi)始的時(shí)候?qū)嵗涣?#xff0c;因?yàn)樵摼€程的Looper對(duì)象
??????????? //還不存在呢。現(xiàn)在可以實(shí)例化了
??????????? //這里L(fēng)ooper.myLooper()獲得的就是該線程的Looper對(duì)象了
??????????? handler = new ThreadHandler(Looper.myLooper());
????????????
??????????? //這個(gè)方法,有疑惑嗎?
??????????? //其實(shí)就是一個(gè)循環(huán),循環(huán)從MessageQueue中取消息。
??????????? //不經(jīng)常去看看,你怎么知道你有新消息呢???
??????????? Looper.loop();?
??????? }
????????
??????? //定義線程類(lèi)中的消息處理類(lèi)
??????? class ThreadHandler extends Handler{
????????????
??????????? public ThreadHandler(Looper looper){
??????????????? super(looper);
??????????? }
????????????
??????????? public void handleMessage(Message msg){
??????????????? //這里對(duì)該線程中的MessageQueue中的Message進(jìn)行處理
??????????????? //這里我們?cè)俜祷亟o主線程一個(gè)消息
??????????????? handler = new MyHandler(Looper.getMainLooper());
????????????????
??????????????? Message msg2 = handler.obtainMessage(1,1,1,"子線程收到:"+(String)msg.obj);
????????????????
??????????????? handler.sendMessage(msg2);
??????????? }
??????? }
??? }
}
4、其他線程給自己發(fā)送Message?
package test.message;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
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) {
??????????????? //啟動(dòng)線程
??????????????? new MyThread().start();????
??????????? }
??????? });
??? }
????
??? class MyHandler extends Handler{
????????
??????? public MyHandler(Looper looper){
??????????? super(looper);
??????? }
????????
??????? public void handleMessage(Message msg){
??????????? super.handleMessage(msg);
??????????? textView.setText((String)msg.obj);
??????? }
??? }????
????
??? class MyThread extends Thread{
????????
??????? public void run(){
??????????? Looper.prepare(); //創(chuàng)建該線程的Looper對(duì)象
??????????? //這里L(fēng)ooper.myLooper()獲得的就是該線程的Looper對(duì)象了
??????????? handler = new ThreadHandler(Looper.myLooper());
??????????? Message msg = handler.obtainMessage(1,1,1,"我自己");
??????????? handler.sendMessage(msg);
????????????
??????????? Looper.loop();?
??????? }
????????
??????? //定義線程類(lèi)中的消息處理類(lèi)
??????? class ThreadHandler extends Handler{
????????????
??????????? public ThreadHandler(Looper looper){
??????????????? super(looper);
??????????? }
????????????
??????????? public void handleMessage(Message msg){
??????????????? //這里對(duì)該線程中的MessageQueue中的Message進(jìn)行處理
??????????????? //這里我們?cè)俜祷亟o主線程一個(gè)消息
??????????????? //加入判斷看看是不是該線程自己發(fā)的信息
??????????????? if(msg.what == 1 && msg.obj.equals("我自己")){
????????????????????
??????????????????? handler = new MyHandler(Looper.getMainLooper());
????????????????????
??????????????????? Message msg2 = handler.obtainMessage(1,1,1,"稟告主線程:我收到了自己發(fā)給自己的Message");
????????????????????
??????????????????? handler.sendMessage(msg2);????????????????
??????????????? }
??????????? }
??????? }
??? }
}
附注:
上面四個(gè)例子的布局文件是同一個(gè)文件main.xml
< ?xml version="1.0" encoding="utf-8"?>
< LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
??? androidrientation="vertical"
??? android:layout_width="fill_parent"
??? android:layout_height="fill_parent"
??? >
< TextView? android:id="@+id/view_01"
??? android:layout_width="fill_parent"?
??? android:layout_height="wrap_content"?
??? android:text="@string/hello"
??? />
????
< Button android:id="@+id/btn_01"?
??? android:layout_width="fill_parent"?
??? android:layout_height="wrap_content"?
??? android:text="測(cè)試消息" />
< /LinearLayout>
本文轉(zhuǎn)自Work Hard Work Smart博客園博客,原文鏈接:http://www.cnblogs.com/linlf03/p/3431227.html,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者
總結(jié)
以上是生活随笔為你收集整理的Message,MessageQueue,Looper,Handler详解+实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Luy 1.0 :一个React-lik
- 下一篇: 全局替换字体,开源库更方便!!!