Handler原理浅析-创新互联

 理解Handler的原理首先要搞清楚什么是Looper,在我的上一篇博文中对此有专门的介绍。Looper的作用是开启一个消息循环,从MessageQueue(Message队列,是Looper的成员变量)中循环取出消息处理。一个线程要使用Handler来处理来自其它线程的消息,这个线程必须有且仅有一个Looper对象与之绑定,也可以说一个Looper对象是是与一个线程一一对应的。

创新互联基于成都重庆香港及美国等地区分布式IDC机房数据中心构建的电信大带宽,联通大带宽,移动大带宽,多线BGP大带宽租用,是为众多客户提供专业四川联通机房服务器托管报价,主机托管价格性价比高,为金融证券行业服务器托管,ai人工智能服务器托管提供bgp线路100M独享,G口带宽及机柜租用的专业成都idc公司。

   Hander有一个Looper类型的成员,在Handler的构造函数(new Handler()或者new Handler(CallBack))中会实例化这个Handler的Looper成员,Handler()构造函数的源码如下:

public Handler() {

        //获得当前线程在 ThreadLocal 中所对应的 Looper

        mLooper = Looper.myLooper();

        if (mLooper == null) {

            throw new RuntimeException(

                "Can't create handler inside thread that has not called Looper.prepare()"               );

        }

        mQueue = mLooper.mQueue;

        mCallback = null;

}

 在Handler构造函数中实例化的Looper不是通过new关键字来实例化的,而是从Looper.myLooper()这个静态方法中取得的。而Looper.myLooper()又是从哪来取得的Looper对象呢?这就涉及到另外一个类ThreadLocal。Looper有一个静态变量是ThreadLocal类型的:

static final ThreadLocal sThreadLocal = new ThreadLocal();

 这个变量就是保存每一个线程和这个线程对应的Looper。这样设计的作用是保证每一个线程的Looper是唯一的。

每一个线程在new Handler()之前必须为这个线程创建Looper对象,使用Looper.prepare()方法创建。

Looper.prepare的源码如下:

public static void prepare() {

        //调用此方法的线程是否在 全局变量 sThreadLocal(即Map)中存有一组以此线程为键的键值对

        if (sThreadLocal.get() != null) {

            throw new RuntimeException("Only one Looper may be created per thread");

        }

        //如果在Map中没有存放当前线程对应的键值对当存入

        // 一个 set 操作,其实就是在 Map 中插入了一组 值,即 <调用此方法的线程,new Looper()>

        // new Looper() 时,Looper的构造函数就会实例化一个 MessageQueue

        sThreadLocal.set(new Looper());

关键是sThreadLocal.set(new Looper());这条语句,它会把new 出来的Looper保存到ThreadLocal这个全局变量中。

有一个问题,就是为什么我们在主线程中new Handler(){...}之前不需要使用Looper.prepare()呢?因为在主线程执行之前,android虚拟机已经帮我们执行了这段代码,因此在主线程中创建Handler对象不需要再新建Looper对象。创建了Handler之后,还要使用Looper.loop()开启消息循环来取消息。主线程也不需要这句代码。

总结:

Looper负责开启消息循环,从MessageQueue中读取Message,由Handler负责处理读出来的Message。

Looper和它的MessageQueue与某一个线程是一一对应的。

使用Handler之前需要使用Looper.prepare()为当前线程创建Looper对象。

使用Looper.loop()开启消息循环。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


文章名称:Handler原理浅析-创新互联
URL链接:http://azwzsj.com/article/dpedes.html