美文网首页android基础AndroidAndroid
异步消息处理机制Handler

异步消息处理机制Handler

作者: cxm11 | 来源:发表于2016-04-10 21:42 被阅读2295次

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


    解析异步消息处理机制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的经典总结

    相关文章

      网友评论

      • notrynobug:handler 还会造成内存泄露
      • jeepc:Android主线程是线程不安全的,这句话应该改成更新ui操作是线程不安全的

      本文标题:异步消息处理机制Handler

      本文链接:https://www.haomeiwen.com/subject/dbqblttx.html