Looper与Handle是Android独有的新概念,但我们学习中常常将他们分开学习,实际上两者密不可分。
Looper与Handle的关系:
Looper是负责在线程里建立消息循环的类,包括准备,开始循环,停止等整个消息循环的生命周期。Handle是负责不同线程之间消息的类,包括消息的发送,接受,清除等消息的生命周期。
但是只有存在Looper的线程,才会用到Handle。没有Handle,Looper无法接收消息,也就无法实现功能。
我们通过Looper与Handle的源码来分析:
Looper.java

    private static final ThreadLocal sThreadLocal = new ThreadLocal();      public static final void prepare() {              if (sThreadLocal.get() != null) {                  throw new RuntimeException("Only one Looper may be created per thread");              }              sThreadLocal.set(new Looper());      }  

这里说明通过prepare()创建Looper对象。同时Android也规定一个线程只能有一个Looper。
由上new Looper(),我们看 Looper的构造方法。

final MessageQueue mQueue;  private Looper() {          mQueue = new MessageQueue();          mRun = true;          mThread = Thread.currentThread();      } 

可以看到在Looper的构造函数中,创建了一个消息队列对象mQueue,此时,调用Looper. prepare()的线程就建立起一个消息循环的对象。

再开始看Handle的源码:
Handle.java

    final MessageQueue mQueue;       final Looper mLooper;      public Handler() {              if (FIND_POTENTIAL_LEAKS) {                  final Class<? extends Handler> klass = getClass();                  if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                          (klass.getModifiers() & Modifier.STATIC) == 0) {                      Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                          klass.getCanonicalName());                  }              }              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;      }  

倒数第五行”Can’t create handler inside thread that has not called Looper.prepare()” 说明Handle的使用必须存在 Looper.prepare(),即必须存在信息队列,这样Handle才能找到信息。Handler通过mLooper = Looper.myLooper()绑定到线程的局部变量Looper上去,同时Handler通过mQueue =mLooper.mQueue获得线程的消息队列。

而没有Handle处理信息即handleMessage (Message msg){},只有Looper的信息队列在循环,信息就没有价值,用武之地。

而我们平时用Handle时,只是在UI线程中却没有声明Looper,是因为UI线程本身默认含有Looper机制。这个我们程序报错时经常看到“looper”。

最后总结工作原理:
1、 初始化Looper,启动消息循环。

2、 绑定handler到CustomThread实例的Looper对象

3、 在Looper循环中,通过Handle发送或一直等待消息。

4、 Handle通过Looper得到消息,处理消息。

附代码实例和更多Looper实现机制源码:

    package com.zhuozhuo;      import android.app.Activity;      import android.os.Bundle;      import android.os.Handler;      import android.os.Looper;      import android.os.Message;      import android.util.Log;      import android.view.View;      import android.view.View.OnClickListener;      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、启动消息循环              }          }      }  

Google源码:

private class Worker implements Runnable {        private final Object mLock = new Object();        private Looper mLooper;        /**         * Creates a worker thread with the given name. The thread         * then runs a {@link android.os.Looper}.         * @param name A name for the new thread         */        Worker(String name) {            Thread t = new Thread(null, this, name);            t.setPriority(Thread.MIN_PRIORITY);            t.start();            synchronized (mLock) {                while (mLooper == null) {                    try {                        mLock.wait();                    } catch (InterruptedException ex) {                    }                }            }        }        public Looper getLooper() {            return mLooper;        }        public void run() {            synchronized (mLock) {                Looper.prepare();                mLooper = Looper.myLooper();                mLock.notifyAll();            }            Looper.loop();        }        public void quit() {            mLooper.quit();        }    }

更多相关文章

  1. 面试官:说说Android的UI刷新机制?
  2. Android(安卓)Handler 消息机制(解惑篇)
  3. Android(安卓)NDK(八):JNI多线程
  4. Android(安卓)NDK的C/C++代码中利用JNI回调实现字符编码转换
  5. Android平台上关于IM的实践总结
  6. Android推送通知的实现--通过 WebSphere MQ 遥测传输 (MQTT) 将
  7. Android与线程
  8. Android(安卓)Asynctask与Handler的比较,优缺点区别,Asynctask源码
  9. android之AsyncTask异步加载的简介(一)

随机推荐

  1. DeepMind PotArt多任务深度强化学习获突
  2. 大数据凉了?No,流式计算浪潮才刚刚开始!
  3. 作为普通Ruby开发,我如何从零转型机器学习
  4. 一文看懂Pinterest如何构建时间序列数据
  5. 6大最常用的Java机器学习库一览
  6. 9月份最热门的机器学习开源项目TOP 5
  7. AI面试必备!你不可不知的10个深度学习方法
  8. 挑战谷歌英伟达?华为披露芯片+AI解决方案!
  9. 抛开炒作看知识图谱,为什么现在才爆发?
  10. 外媒:谷歌Dragonfly项目仍在推进,6-9个月内