handler与looper的关系及HandlerThread

做了也快2年的android了,发现android的机制还不是很了解,这几天看了一下这方面的介绍,总结一下handler的用法和机制。

handler就是用来线程之间通信的,主线程与子线程。一般的用法是,子线程通知ui主线程的handler去刷新ui操作。最近遇到一些人,问能不能主线程去通知子线程的handler。

当然是可以的。贴一个例子

package cc.c;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;
/**
 * Demo描述:
 *
 * 示例步骤如下:
 * 1 子线程给子线程本身发送消息
 * 2 收到1的消息后,子线程给主线程发送消息
 * 3 收到2的消息后,主线程给子线程发送消息
 *
 * 为实现子线程给自己本身发送消息,关键还是在于构造Handler时传入的Looper.
 * 在此就传入该子线程自己的Looper即调用Looper.myLooper(),代码如下:
 * Looper.prepare();
 * mHandlerTest1=new HandlerTest1(Looper.myLooper());
 * Looper.loop();
 *
 * 所以当mHandlerTest1.sendMessage(message);发送消息时
 * 当然是发送到了它自己的消息队列.
 *
 * 当子线程中收到自己发送的消息后,可继续发送消息到主线程.此时只要注意构造
 * Handler时传入的Handler是主线程的Handler即可,即getMainLooper().
 * 其余没啥可说的.
 *
 *
 * 在主线程处理消息后再发消息到子线程
 *
 *
 * 其实这些线程间发送消息,没有什么;关键还是在于构造Handler时传入谁的Looper.
 *
 */
public class MainActivity extends Activity {
    private TextView mTextView;
    private HandlerTest1 mHandlerTest1;
    private HandlerTest2 mHandlerTest2;
    private int counter=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
    }

    private void init() {
        mTextView = (TextView) findViewById(R.id.textView);

        //1 子线程发送消息给本身
        new Thread() {
            public void run() {
                Looper.prepare();
                mHandlerTest1=new HandlerTest1(Looper.myLooper());
                Message message = new Message();
                message.obj = "子线程发送的消息Hi~Hi";
                mHandlerTest1.sendMessage(message);
                Looper.loop();
            };
        }.start();

    }

    private class HandlerTest1 extends Handler {

        private HandlerTest1(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            System.out.println("子线程收到:" + msg.obj);

            //2  收到消息后可再发消息到主线程
            mHandlerTest2=new HandlerTest2(getMainLooper());
            Message message = new Message();
            message.obj = "O(∩_∩)O";
            mHandlerTest2.sendMessage(message);
        }
    }

    private class HandlerTest2 extends Handler {

        private HandlerTest2(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            mTextView.setText("在主线程中,收到子线程发来消息:" + msg.obj);

            //3  收到消息后再发消息到子线程
            if (counter==0) {
                Message message = new Message();
                message.obj = "主线程发送的消息Xi~Xi";
                mHandlerTest1.sendMessage(message);
                counter++;
            }

        }
    }

}

这个就很好的展示了,子线程主线程都是可以有handler,可以互相传递消息的。必须要明确的是handler必须要绑定一个looper。但是区别在于,子线程需要做
Looper.prepare();
Looper.loop();这两个方法,而主线程不需要。因为主线程在启动的时候会初始化looper,如下:

 Android程序的运行入口点可以认为是android.app.ActivityThread类的main()方法(源码2.3.3):

    public static final void main(String[] args) {
        // other codes...

        // 创建主线程循环
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        // other codes...

        // 进入当前线程(此时是主线程)消息循环
        Looper.loop();

        // other codes...

        thread.detach();
        // other codes...
    }

所以可以看到,如果要有消息循环的话,线程中任何时候都必须要有初始化looper的过程,只不过主线程在启动的时候已经帮我们完成,而子线程需要自己去实现。(需要注意的是,如果我们在ui线程中new handler而不做绑定,那么默认的认为handler是绑定主线程的looper,所以我们就可以想到,ui线程中new handler也可以绑定子线程的looper,即handlerThread的用法)

另外一个是,handlerThread,参考下面的解释:

在上面的总结中指出,Android的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper。事实上Android提供了一个封装好的带有looper的线程类,即为HandlerThread,具体可参见下面的代码:

public class HandlerThreadActivity extends Activity {

    private static final String TAG = "HandlerThreadActivity";

    private HandlerThreadmHandlerThread;

    private MyHandler mMyHandler;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

       // TODO Auto-generatedmethod stub

       super.onCreate(savedInstanceState);

       TextView text = new TextView(this);

       text.setText("HandlerThreadActivity");

       setContentView(text);

       Log.d(TAG, "The mainthread id = " +      Thread.currentThread().getId());

       //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,

       //这个类由Android应用程序框架提供

       mHandlerThread = new HandlerThread("handler_thread");

       //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();

       mHandlerThread.start();

       //即这个Handler是运行在mHandlerThread这个线程中

       mMyHandler = new MyHandler(mHandlerThread.getLooper());

       mMyHandler.sendEmptyMessage(1);

    }

    private class MyHandler extends Handler {

       public MyHandler(Looper looper) {

           super(looper);

       }

       @Override

       public void handleMessage(Message msg) {

           Log.d(TAG, "MyHandler-->handleMessage-->threadid = " + Thread.currentThread().getId());

           super.handleMessage(msg);

       }

    }

}

可以看到在该段代码中,在子线程中有 mHandlerThread = new HandlerThread("handler_thread"),然后在主线程中的hanler是绑定该线程的loooper的,mMyHandler = new MyHandler(mHandlerThread.getLooper());

我的理解的话,HandlerThread与thread的区别不大,因为HandlerThread是继承自thread的,只不过HandlerThread提供了默认的Looper。

总结一下:

1、handler是android提供的一种消息循环机制,为多线程提供了很大的帮助,特别是异步获取数据然后刷新ui的操作。

2、handler与looper是共生的,一个线程只有一个looper,只不过有的线程已经做好了初始化looper的操作(ui线程,HandlerThread),而其他子线程需要自己做。

3、handler通过绑定特定线程的looper,可以实现在该线程中向某一个looper发送消息,就可以在这个handler中处理了。如子线程中通过

Looper.prepare();mHandlerTest1=new HandlerTest1(Looper.myLooper());绑定自己的looper,也可以mHandlerTest2=new HandlerTest2(getMainLooper());绑定ui的looper都是可以的,然后主线程中也棒子子线程的looper,就看你如何绑定哪个looper了。
				
时间: 2024-10-13 21:36:36

handler与looper的关系及HandlerThread的相关文章

Android开发之Handler和Looper的关系

关于Handler的总结. Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理. Handler:处理者,负责Message的发送及处理.使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等. MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行.当然,存放Message并非实际意义的保存,而

Handler,Message,Looper的关系

Android系统中,Java的应用程序和其他的系统相同,都是靠消息驱动工作的,大致的工作原理是: 有一个消息队列,可以往这个消息队列中投递消息. 有一个消息循环,不断从消息队列中取出消息,然后处理. 在Android系统中,这些工作主要是由Looper和Handler类来实现. Looper类,用于封装消息循环,并且有一个消息队列. Hanlder类,有点像辅助类,它封装消息投递,消息处理等接口. Looper类分析 在线程中有一个线程局部变量类,调用Looper的prepare()方法,会在

Android异步消息处理 Handler Looper Message关系源码分析

# 标签: 读博客 对于Handler Looper Message 之前一直只是知道理论,知其然不知所以然,看了hongyang大神的源码分析,写个总结帖. 一.概念.. Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念. 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环.若消息队列为空,线程则会阻塞等待. 说了这一堆,那么和Handle

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

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 很多人面试肯定都被问到过,请问Android中的Looper , Handler , Message有什么关系?本篇博客目的首先为大家从源码角度介绍3者关系,然后给出一个容易记忆的结论. 1. 概述 Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念.那么什么叫异步消息处理线程呢?异步

Android 异步消息处理机制Looper、Handler、Message三者关系

Looper,Handler,Message三者是我们常常用来再子线程跟新UI的,我们把Message发给Handler,然后,handler调用HandlerMessage()方法,我们在这个方法里面更新UI.那么Looper呢,又是什么,下面我来给大家介绍一下三者的关系. 首先要说明的是,每个线程最多只有一个Looper,在线程里面调用Looper.prepare()就是为这个线程设置了一个Looper,所以在子线程,我们使用这个三者前,一定要调用Looper.prepare()方法,而主线

正确理解 AsyncTask,Looper,Handler三者之间的关系(基于android 4.0)

Looper 和Handler 是理解好AsyncTask的一个基础,我们可以先从这里开始,先给出一个主线程和子线程互相通信的例子. 1 package com.example.loopertest; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Looper; 7 import android.os.Message; 8

简析Handler、Looper和MessageQueue三者的关系

Android开发中,Handler用的非常多,因为它和AsyncTask一样是系统提供给我们的异步的通信机制.能够将一些更新和别的不适合放在UI主线程的操作放到它们中去. Handler的作用主要有两个:一是在线程中发送消息, 二是获取和处理消息.既可以发送消息sendEmptyMessage(int what) ,也可以发送指定的消息sendMessage(Message msg),还可以利用msg.obj的属性去传递我们需要的参数甚至对象,使原本的通信机制更为强大. Handler发送消息

handler、looper、messagequeue之间的关系

这里先简单的写一个例子,后续会更新一些概念性的东西在里面.因为现在还不太理解这个. 1.只是听讲:handler是负责消息传输,looper负责消息回调,messagequeue是一个存储消息的容器. 2.在子线程中,要想实现消息的传送,需要获得looper对象进行回调. package com.example.handledemos; import android.app.Activity; import android.os.Bundle; import android.os.Handler

Handle的原理(Looper、Handler、Message三者关系)

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Handle的原理(Looper.Handler.Message三者关系) - Ansen - 博客频道 - CSDN.NET Ansen 当我们失去了青春的时候,起码我们还留下了代码...... 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &n