异步消息处理机制Handler

异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。


解析异步消息处理机制Handler

Android中的异步消息处理主要由四个部分组成,Message、Handler、MessageQueue和Looper。

  1. Message
    Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。上一小节我们使用到了Message的what字段,初次之外还可以使用arg1和arg2字段来携带一些整型数据,使用obj字段携带一个Object对象。
  2. Handler
    Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler的handleMessage()方法中。
  3. MessageQueue
    MessageQueue是消息队列的意思,它主要是用于存放所有的Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只有一个MessageQueue对象。
    4.Looper
    Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()方法中。每个线程中也只会有一个Looper对象。

首先需要在主线程当中创建一个Handler对象,并重写handleMessage()方法。然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条信息发送出去。之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,最后分发回Handler的handleMessage()方法中。由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线程运行,于是我们在这里就可以安心地进行UI操作了。


Android异步消息处理机制让你深入理解Looper、Handler、Message三者关系

Looper主要是prepare()和loop()两个方法

一个线程中只有一个Looper实例
looper方法必须在prepare方法之后运行。

Looper主要作用:

1、 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
2、 loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。好了,我们的异步消息处理线程已经有了消息队列(MessageQueue),也有了在无限循环体中取出消息的哥们,现在缺的就是发送消息的对象了,于是乎:Handler登场了。

Handler

使用Handler之前,我们都是初始化一个实例,比如用于更新UI线程,我们会在声明的时候直接初始化,或者在onCreate中初始化Handler实例

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
好了,总结完成,大家可能还会问,那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法

在主线程中可以直接创建Handler对象,而在子线程中需要先调用Looper.prepare()才能创建Handler对象。


1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。大家可能还会问,那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,并与Looper实例中的MessageQueue相关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。


Handler+Looper+MessageQueue深入详解

概述:Android使用消息机制实现线程间的通信,线程通过Looper建立自己的消息循环,MessageQueue是FIFO的消息队列,Looper负责从MessageQueue中取出消息,并且分发到消息指定目标Handler对象。Handler对象绑定到线程的局部变量Looper,封装了发送消息和处理消息的接口。

实例:我们先介绍Android线程通讯的一个例子,这个例子实现点击按钮之后从主线程发送消息"hello"到另外一个名为” CustomThread”的线程。


package
import

public class LooperThreadActivity extends Activity{
/** Called when the activity is first created. */

private final int MSG_HELLO = 0;
private Handler mHandler;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new CustomThread().start();  //新建并启动CustomThread实例

findViewById(R.id.send_btn).setOnClickListener(new OnClickListener(){
@Override
        public void onClick(View v) {//点击界面时发送消息
            String str = "hello";
            Log.d("Test", "MainThread is ready to send msg:" + str);
            mHandler.obtainMessage(MSG_HELLO, str).sendToTarget();//发送消息到CustomThread实例
             
        }
    });
}

class CustomThread extends Thread{
@Override
public void run() {
 //建立消息循环的步骤
        Looper.prepare();//1、初始化Looper
        mHandler = new Handler(){//2、绑定handler到CustomThread实例的Looper对象
            public void handleMessage (Message msg) {//3、定义处理消息的方法
                switch(msg.what) {
                case MSG_HELLO:
                    Log.d("Test", "CustomThread receive msg:" + (String) msg.obj);
                }
            }
        };
        Looper.loop();//4、启动消息循环
    }
}
}

我们看到,为一个线程建立消息循环有四个步骤:

  1. 初始化Looper

  2. 绑定handler到CustomThread实例的Looper对象

  3. 定义处理消息的方法

  4. 启动消息循环

  5. 初始化Looper:Looper.prepare()
    一个线程在调用Looper的静态方法prepare()时,这个线程会新建一个Looper对象,并放入到线程的局部变量中,而这个变量是不和其他线程共享的。

在Looper的构造函数中,创建了一个消息队列对象mQueue,此时,调用Looper.prepare()的线程就建立起一个消息循环的对象(此时还没开始进行消息循环)。

  1. 绑定handler到CustomThread实例的Looper对象:mHandler = new Handler()

Handler通过mLooper= Looper.myLooper();绑定到线程的局部变量Looper上去,同时Handler通过mQueue = mLooper.mQueue;获得线程的消息队列。此时,Handler就绑定到创建此Handler对象的线程的消息队列上了。

  1. 定义处理消息的方法:Override public void handleMessage(Message msg){}
    子类需要覆盖这个方法,实现接收到消息后的处理方法。

  2. 启动消息循环:Looper.loop()


使用Thread+Handler实现非UI线程更新UI界面

public class ThreadhandlerActivity extends Activity{
private static final int MSG_SUCCESS = 0;
private static final int MSG_FAILURE = 1;

private Thread mThread;

private Handler mHandler = new Handler(){
public void handleMessage(Message msg){//此方法在ui线程运行
switch(msg.what) {
case MSG_SUCCESS:
 mImageView.setImageBitmap((Bitmap) msg.obj);//imageview显示从网络获取到的logo
            Toast.makeText(getApplication(), getApplication().getString(R.string.get_pic_success), Toast.LENGTH_LONG).show();
            break;
        case MSG_FAILURE:
            Toast.makeText(getApplication(), getApplication().getString(R.string.get_pic_failure), Toast.LENGTH_LONG).show();
            break;
        }
    }
};
  @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mImageView= (ImageView) findViewById(R.id.imageView);//显示图片的ImageView
    mButton = (Button) findViewById(R.id.button);
    mButton.setOnClickListener(new OnClickListener() {
         
        @Override
        public void onClick(View v) {
            if(mThread == null) {
                mThread = new Thread(runnable);
                mThread.start();//线程启动
            }
            else {
                Toast.makeText(getApplication(), getApplication().getString(R.string.thread_started), Toast.LENGTH_LONG).show();
            }
        }
    });
}
 
Runnable runnable = new Runnable() {
     
    @Override
    public void run() {//run()在新的线程中运行
        HttpClient hc = new DefaultHttpClient();
        HttpGet hg = new HttpGet("http://www.oschina.net/img/logo.gif");//获取oschina的logo
        final Bitmap bm;
        try {
            HttpResponse hr = hc.execute(hg);
            bm = BitmapFactory.decodeStream(hr.getEntity().getContent());
        } catch (Exception e) {
            mHandler.obtainMessage(MSG_FAILURE).sendToTarget();//获取图片失败
            return;
        }
        mHandler.obtainMessage(MSG_SUCCESS,bm).sendToTarget();//获取图片成功,向ui线程发送MSG_SUCCESS标识和bitmap对象

//          mImageView.setImageBitmap(bm); //出错!不能在非ui线程操作ui元素

//          mImageView.post(new Runnable() {//另外一种更简洁的发送消息给ui线程的方法。
//              
//              @Override
//              public void run() {//run()方法会在ui线程执行
//                  mImageView.setImageBitmap(bm);
//              }
//          });
    }
    };
 
}

Android开发中Handler的经典总结

当应用程序启动时,Android首先会开启一个主线程(也叫UI线程),主线程为管理界面中的UI控件,进行事件分发。

  1. Handler定义
    主要接收子线程发送的数据,并用此数据配合主线程更新UI。

Android主线程是线程不安全的,更新UI只能在主线程中更新,子线程中操作是危险的。
Handler运行在主线程中,它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接收子线程传过来的(子线程用sendMessage()方法传递)Message对象,(里面包含数据),把这些消息放入主线程队列中,配合主线程进行更新UI。

  1. Handler一些特点
    Handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建它的线程池中(一般是位于主线程),它有两个作用:
    (1)安排消息或Runnable在某个主线程中某个地方执行;
    (2)安排一个动作在不同的线程中执行。
    Handler中分发消息的一些方法

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)

以上post类方法允许你安排一个Runnable对象到主线程队列中,sendMessage类方法,允许你安排一个带数据的Message对象到队列中,等待更新。

  1. Handler实例
    子类需要继承Handler类,并重写handleMessage(Message msg)方法,用于接收线程数据。
public class MyHandlerActivity extends Activity {
Button button;
MyHandler myHandler;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handlertest);

button = (Button)     findViewById(R.id.button);
myHandler = new MyHandler();
//当创建一个新的Handler实例时,它会绑定到当前线程和消息的队列中,开始分发数据
//Handler有两个作用:(1)定时执行Message和Runnable对象
//(2):让一个动作,在不同的线程中执行。

//它安排消息,用以下方法
//post(Runnable)
//postAtTime(Runnable, long)
// postDelayed(Runnable, long)
//sendEmptyMessage(int)
//sendMessage(Message)
//sendMessageAtTime(Message, long)
//sendMessageDelayed(Message, long)

//以上方法以post开头的允许你处理Runnable对象
//sendMessage()允许你处理Message对象(Message里可以包含数据)
MyThread m = new MyThread();
new Thread(m).start();
}

/**
* 接收消息,处理消息,此Handler会与当前主线程一块运行
**/

class MyHandler extends Handler {
public MyHandler(){
}

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

//子类必须重写此方法,接收数据
@Override
public void handleMessage(Message msg){
// TODO Auto-generated method stub
Log.d("MyHandler","handleMessage....");
super.handleMessage(msg);
//此处可以更新UI
Bundle b = msg.getDada();
String color = b.getString("color");
MyHandlerActivity.this.button.append(color);
}
}

class MyThread implements Runnable{
public void run(){
try{
Thread.sleep(10000);
} catch(InterruptedException e){
//TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("thread....","mThread....");
Message msg = new Message();
Bundle b = new Bundle(); //存放数据
b.putString("color","我的");
msg.setData(b);

MyHandlerActivity.this.myHandler.sendMessage(msg);//向Handler发送消息,更新UI
}
}
}

一个Handler允许你发送和处理消息以及与一个线程的消息队列相关的Runnable对象。每个Handler实例都和单个线程以及该线程的消息队列有关。当你创建了一个新handler,它就会和创建它的线程/消息队列绑定,在那以后,它就会传递消息以及runnable对象给消息队列,然后执行它们。

需要使用Handler有两大主要的原因:
(1)在将来的某个时间点调度处理消息和runnable对象;
(2)将需要执行的操作放到其他线程之中,而不是自己的

若在主线程中实例化一个Handler对象,例如:
Handler mHandler = new Handler();
此时它并没有新派生一个线程来执行此Handler,而是将此Handler附加在主线程上,故此时若你在Handler中执行耗时操作的话,还是会弹出ANR对话框!


创建Handler

  1. 使用默认的构造方法:new Handler()
  2. 使用带参的构造方法,参数是一个Runnable对象或者回调对象

Handler只是简单地往消息队列中发送消息而已
它们有更方便的方法可以帮助与UI线程通信。

在Android,线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper。我们的主线程(UI线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入了一个新的机制Handler,我们有消息循环,就要往消息循环里面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,消息的处理,把这些都封装在Handler里面,注意Handler只是针对那些有Looper的线程,不管是UI线程还是子线程,只要你有Looper,我就可以往你的消息队列里面添加东西,并做相应的处理。

如果在子线程里面新建handler,就会出现错误,原因就是一个线程对应一个或零个Looper和MessageQueue。handler是一种消息机制,而子线程的启用默认是没有Looper对象的(主线程有),所以在子线程使用Handler对象的时候,要先使用Looper.prepare(),启用一个Looper,然后新建Handler对象,再使用Looper.loop().
至此子线程就有了自己的Looper,可以接收和处理信息。

android.os.Looper:

Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。

注:写在Looper.loop()之后的代码不会被立即执行,当调用后mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。

一个典型的Looper Thread实现:

class LooperThread extends Thread {      
public Handler mHandler;      
public void run() {          
Looper.prepare();          
mHandler = new Handler() {              
public void handleMessage(Message msg) {                
// process incoming messages here              
}          
};          
Looper.loop();      
}  
}

android.os.Handler:

Handler用于跟线程绑定,来向线程的消息循环里面发送消息、接收消息并处理消息。

通过以下函数来向线程发送消息或Runnable:

1.post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long);
当线程接收到Runnable对象后即立即或一定延迟调用。
2.sendEmptyMessage(int), sendMessage(Message)
, sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long)。
当线程接受到这些消息后,根据你的Handler重构的handleMessage(Message)根据接收到的消息来进行处理。

一个Activity主线程中可以有多个Handler对象,但MessageQueue是只有一个,对应的Looper也是只有一个。

Looper类的静态成员函数prepareMainLooper是专门应用程序的主线程调用的,为了让其它地方能够方便地通过Looper类的getMainLooper函数来获得应用程序主线程中的消息循环对象。


Android Handler详细使用方法实例

handler使用例1.

这个例子是最简单的介绍handler使用的,是将handler绑定到它所建立的线程中。

单击Start按钮,程序会开始启动线程,并且线程程序完成后延时1s会继续启动该线程,每次线程的run函数中完成对界面输出nUpdateThread…文字,不停的运行下去,当单击End按钮时,该线程就会停止,如果继续单击Start,则文字又开始输出了。

MainActivity.java;
主要代码

public class MainActivity extends Activity{

//使用handler时首先要创建一个handler对象
Handler  handler = new Handler();
//要用Handler来处理多线程可以使用Runnable接口,这里先定义该接口
//线程中运行该接口的run函数
Runnable update_thread = new Runnable()
{
public void run()
{
handler.postDelayed(update_thread,1000);
}
};
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState    );
...
}
//btn监听实现
//调用handler的post方法,将要执行的线程对象添加到队列当中
//将线程接口立刻送到线程队列
handler.post(update_thread);
//将接口从线程队列中移除
handler.removeCallbacks(update_thread);
}

post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。

为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程上的消息队列中处理传过来的Runnable对象和消息。

这个例子将学会怎样不使用runnable来启动一个线程,而是用HandlerThread的looper来构造一个handler,然后该handler自己获得消息,并传递数据,然后又自己处理消息,当然这是在另一个线程中完成的。
消息结构中传递简单的整型可以采用它的参数arg1和arg2,或者传递一些小的其它数据,可以用它的object,该object可以是任意的对象。当需要传送比较大的数据是,可以使用消息的setData方法,该方法需要传递一个Bundle的参数。Bundle中存放的是键值对的map,只是它的键值类型和数据类型比较固定而已。

public class HandleTest2 extends Activity{

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState  );
setContentView(R.layout.main);
//生成一个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发送到自己的handler中
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");
}
}
}

这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送完成时候继续进行,不会影响当前的操作。
这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程。

android中handler用法总结

另外再强调一遍,在UI线程(主线程)中:

mHandler=new Handler();
mHandler.post(new Runnable(){
void run(){
   //执行代码..
 }
});
这个线程其实是在UI线程之内运行的,并没有新建线程。

常见的新建线程的方法是:

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

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

Handler+Looper+MessageQueue深入详解

1.主线程给自己发送Message

Looper looper = Looper.getMainLooper();//获取主线程的Looper对象
//这里以主线程的Looper对象创建了handler, 
//所以,这个handler发送的Message会被传递给主线程的MessageQueue。
handler = new MyHandler(looper);     
handler.removeMessages(0);
//构建Message对象 
//第一个参数:是自己指定的message代号,方便在handler选择性地接收 
//第二三个参数没有什么意义 
//第四个参数需要封装的对象
Message msg = handler.obtainMessage(1,1,1,"someword");
handler.sendMessage(msg);//发送消息

2.其他线程给主线程发送Message

public class MainActivity extends Activity {
private Handler handler;
//可以看出这里启动了一个线程来操作消息的封装和发送的工作
new MyThread().start(); 

//加载一个线程类
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(1,1,1,"其他线程发消息了"); 
handler.sendMessage(msg); //发送消息 
} 
}
}
  1. 主线程给其他线程发送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(1,1,1,"主线程发送的消息"); 
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(1,1,1,"子线程收到:"+(String)msg.obj); 
handler.sendMessage(msg2); 
} 
} 
}
}

多个任务的话,还有一个问题,这里是并行还是串行执行?

Android 中Message,MessageQueue,Looper,Handler详解+实例
http://tanghaibo001.blog.163.com/blog/static/9068612020111287218197/


Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
http://blog.csdn.net/lmj623565791/article/details/38377229?utm_source=tuicool&utm_medium=referral

Android开发中Handler的经典总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容