zoukankan      html  css  js  c++  java
  • 线程执行android的looper,handler消息小结

    本文是一篇关于线程执行的帖子

      在Android开发中,为了UI线程能实时响应须要防止在其中执行耗时操作,以防止界面假死甚至ANR。我们一般把耗时操作如下载,查询放在一个单独的线程中。这以后再将结果更新到UI界面。android平台在非UI线程中更新界面大致有以下几种方法:

        

    Activity.runOnUiThread(Runnable) 
    View.post(Runnable) 
    AsyncTask<Params, Progress, Result> 
    Handler.post(Runnable)




    其中后面两种方法我们用的比拟多,而AsyncTask也是基于Handler停止封装的,可以看出Handler是我们更新UI线程的利器。看下经常使用的Handler构造方法:

    public Handler() {
       this(null, false);
    }
    public Handler(Callback callback, boolean async) {
        .....
        mLooper = Looper.myLooper();
        .....
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }



    从第二个方法里面可以看出,新建一个handler对象,主要是使其final MessageQueue mQueue作用域指向一个对象,其它的作用域用默认的都行。mQueue来自mLooper = Looper.myLooper();看下myLooper()方法的实现:

    public static Looper myLooper() { 
        return sThreadLocal.get(); 
    } 
    // sThreadLocal.get() will return null unless you've called prepare(). 
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();


        每日一道理
    当浮华给予我们过多欺骗,现实中的虚假几乎让我们忘却了真的存在,是真情唤回了迷离的心,是真情带给了我们最纯、最真的感觉,它流露的是美的誓言,渗透的是永恒执著的真爱。



         到这里是时候说明下ThreadLocal了,ThreadLocal是java中为每一个线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制。这里我们只要记住以下几点:1.每一个线程中取得的ThreadLocal的值都是线程独立的,和其它线程没有关联。2.对于ThreadLocal的理解在记住第一点的基础上只须要记住public void set(T)和public T get()两个接口就可以。
            事实上android利用ThreadLocal,为每一个UI线程建立一个looper对象,每一个looper对象有一个消息队列MessageQueue。每次声明一个handler,其主要步骤就是绑定当前线程的消息队列,这以后就可以利用handler将须要的操作派发到消息队列中。一般在每一个线程的开始执行Looper.prepare();这是为当前线程创立线程私有的looper对象,这以后就可以声明handler;一般在每一个线程的最后执行Looper.loop();前面说明handler绑定了当前线程的消息队列,loop()方法就是监听消息队列,并且执行操作,因此这个方法是一个无限循环,其以后的代码都不会执行,所以在线程的最后执行。
            这类模式有点像大学操作系统中的生产者和消费者模式,looper就像消费者,handler就像生产者,比拟特殊的是在一个线程中消费者looper只能有一个,生产者handler可以有多个。接下来带着下面的知识看看looper中的主要代码:

    public static void prepare() {
        prepare(true);
    }
     
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
    public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        for (;;) {
            Message msg = queue.next(); // might block
            .....
            msg.target.dispatchMessage(msg);
        }
    }



    在程序中如果某一个子方法里面触及到了handler而当前线程没有绑定looper(比如在某个自己新建的线程中新分配的一个对象就可能须要handler),运行时就会抛出异常:

    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }



        而如果只在线程的开头执行Looper.prepare();而没有执行Looper.loop();就会涌现很多操作不会执行的景象。

             

    文章结束给大家分享下程序员的一些笑话语录: 系统程序员
      1、头皮经常发麻,在看见一个蓝色屏幕的时候比较明显,在屏幕上什幺都看不见的时候尤其明显;
      2、乘电梯的时候总担心死机,并且在墙上找reset键;
      3、指甲特别长,因为按F7到F12比较省力;
      4、只要手里有东西,就不停地按,以为是Alt-F、S;
      5、机箱从来不上盖子,以便判断硬盘是否在转;
      6、经常莫名其妙地跟踪别人,手里不停按F10;
      7、所有的接口都插上了硬盘,因此觉得26个字母不够;
      8、一有空就念叨“下辈子不做程序员了”;
      9、总是觉得9号以后是a号;
      10、不怕病毒,但是很害怕自己的程序;

  • 相关阅读:
    学习视频资料下载论坛
    2007年12月英语四级预测作文大全1
    主板报警声音大全
    2007年12月英语四级预测作文大全1
    主板报警声音大全
    LOGO在线制作
    武汉之行收获
    武汉之行
    心灵小栈: 镌刻在地下500米的母爱
    一道终身受益的测试题
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3089452.html
Copyright © 2011-2022 走看看