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、不怕病毒,但是很害怕自己的程序;

  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3089452.html
Copyright © 2011-2022 走看看