源:http://blog.youkuaiyun.com/illusion_luna/article/details/8222657
先来看一下Looper这个类:
再来看一下handler这个类的google给出的解释:
简单的来说:大家可以这样来理解,有一个消息队列MessageQueue
(队列应该大家都知道了吧。。。。。),我们handler要做的工作就是将一个Message对象都到这个消息队列和负责处理从被消息队列拿出来的Message,那么谁负责遍历和拿取消息队列内的消息给handler呢?没错,这些遍历和拿取的工作就是Looper来完成的。好了,下面来看一下我写的例子(如果有大神飘过的话,别见怪。。别见怪。。。)
先来看一下整个项目的搭构:
其中的布局文件main.xml里面很简单,久一个TextView和一个Button。(不信的话。。。。。我也不给你看)
好了,现在我们来看一下activity里面的代码
- public class HLActivity extends Activity {
- /** Called when the activity is first created. */
- private TextView textView=null;
- private Button btn=null;
- //private Handler handler=null;
- public static int i=0;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- initralWeight();
- /*handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- textView.setText("当前点击运行线程的次数为"+msg.arg1);
- }
- };*/
- }
- private class BtnListener implements OnClickListener{
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- TestThread tt=new TestThread();
- Thread t=new Thread(tt);
- t.start();
- }
- }
- private class TestThread implements Runnable{
- private Handler handler=null;
- @Override
- public void run() {
- // TODO Auto-generated method stub
- Looper.prepare();
- handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- System.out.println("当前的数字为:"+msg.arg1);
- }
- };
- while(i<10){
- Message msg=new Message();
- msg.arg1=i++;
- handler.sendMessage(msg);
- }
- Looper.loop();
- }
- }
- private void initralWeight(){
- textView=(TextView) findViewById(R.id.text);
- btn=(Button) findViewById(R.id.btn);
- btn.setOnClickListener(new BtnListener());
- }
- }
- handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- System.out.println("当前的数字为:"+msg.arg1);
- }
- };
- Looper.prepare();
- Looper.loop();
还有,你说的消息队列到底在哪里?为什么我没看见?
别急,下面我们来看一下关于Looper的源代码:
- public class Looper {
- // 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
- private static final ThreadLocal sThreadLocal = new ThreadLocal();
- // Looper内的消息队列
- final MessageQueue mQueue;
- // 当前线程
- Thread mThread;
- // 。。。其他属性
- // 每个Looper对象中有它的消息队列,和它所属的线程
- private Looper() {
- mQueue = new MessageQueue();
- mRun = true;
- mThread = Thread.currentThread();
- }
- // 我们调用该方法会在调用线程的TLS中创建Looper对象
- public static final void prepare() {
- if (sThreadLocal.get() != null) {
- // 试图在有Looper的线程中再次创建Looper将抛出异常
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper());
- }
- // 其他方法
- }
大家在这里可以看到Looper的构造函数Looper()被声明为private,也就是说,在外部,我们不能直接的使用Looper的构造函数,那么我们该怎样去创建一个Looper对象呢?
- public static final void prepare() {
- if (sThreadLocal.get() != null) {
- // 试图在有Looper的线程中再次创建Looper将抛出异常
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper());
- }
好了,下面是重点:
- public static final void loop() {
- Looper me = myLooper(); //得到当前线程Looper
- MessageQueue queue = me.mQueue; //得到当前looper的MQ
- // 这两行没看懂= = 不过不影响理解
- Binder.clearCallingIdentity();
- final long ident = Binder.clearCallingIdentity();
- // 开始循环
- while (true) {
- Message msg = queue.next(); // 取出message
- if (msg != null) {
- if (msg.target == null) {
- // message没有target为结束信号,退出循环
- return;
- }
- // 日志。。。
- if (me.mLogging!= null) me.mLogging.println(
- ">>>>> Dispatching to " + msg.target + " "
- + msg.callback + ": " + msg.what
- );
- // 非常重要!将真正的处理工作交给message的target,即后面要讲的handler
- msg.target.dispatchMessage(msg);
- // 还是日志。。。
- if (me.mLogging!= null) me.mLogging.println(
- "<<<<< Finished to " + msg.target + " "
- + msg.callback);
- // 下面没看懂,同样不影响理解
- final long newIdent = Binder.clearCallingIdentity();
- if (ident != newIdent) {
- Log.wtf("Looper", "Thread identity changed from 0x"
- + Long.toHexString(ident) + " to 0x"
- + Long.toHexString(newIdent) + " while dispatching to "
- + msg.target.getClass().getName() + " "
- + msg.callback + " what=" + msg.what);
- }
- // 回收message资源
- msg.recycle();
- }
- }
- }
- Looper me = myLooper(); //得到当前线程Looper
- MessageQueue queue = me.mQueue; //得到当前looper的MQ
然后再while内循环这个消息队列,不断的取出数据
- Message msg = queue.next(); // 取出message
- if (msg != null)
- if (msg.target == null) {
- // message没有target为结束信号,退出循环
- return;
- }
- <pre name="code" class="java">// 日志。。。
- if (me.mLogging!= null) me.mLogging.println(
- ">>>>> Dispatching to " + msg.target + " "
- + msg.callback + ": " + msg.what
- );</pre>
- <pre></pre>
- <pre></pre>
- 在下面便是这个方法的核心了。<pre name="code" class="java">msg.target.dispatchMessage(msg);</pre>这个方法实际作用便是将Message传递给Handler类来处理,而Handler使用<pre name="code" class="java">handleMessage</pre>方法来接受,并且处理该信息。
- <p>有些人说了</p>
- <pre name="code" class="java">dispatchMessage</pre>是Handler的方法吧?别急。
- <p>下面我们来看一下dispatchMessage这个方法的内部实现:<span style="color:#008000"><br>
- </span></p>
- <p><span style="color:#008000">//</span><span style="color:#008000"> 处理消息,该方法由looper调用</span><span style="color:#008000"></span><span style="color:#000000">
- </span><span style="color:#0000ff">public</span><span style="color:#000000"> </span>
- <span style="color:#0000ff">void</span><span style="color:#000000"> dispatchMessage(Message msg) {
- </span><span style="color:#0000ff">if</span><span style="color:#000000"> (msg.callback
- </span><span style="color:#000000">!=</span><span style="color:#000000"> </span><span style="color:#0000ff">null</span><span style="color:#000000">) {
- </span><span style="color:#008000">//</span><span style="color:#008000"> 如果message设置了callback,即runnable消息,处理callback!</span><span style="color:#008000"></span><span style="color:#000000"> handleCallback(msg); }
- </span><span style="color:#0000ff">else</span><span style="color:#000000"> { </span>
- <span style="color:#008000">//</span><span style="color:#008000"> 如果handler本身设置了callback,则执行callback</span><span style="color:#008000"></span><span style="color:#000000">
- </span><span style="color:#0000ff">if</span><span style="color:#000000"> (mCallback
- </span><span style="color:#000000">!=</span><span style="color:#000000"> </span><span style="color:#0000ff">null</span><span style="color:#000000">) {
- </span><span style="color:#008000">/*</span><span style="color:#008000"> 这种方法允许让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。见http://alex-yang-xiansoftware-com.iteye.com/blog/850865
- </span><span style="color:#008000">*/</span><span style="color:#000000"> </span><span style="color:#0000ff">if</span><span style="color:#000000"> (mCallback.handleMessage(msg)) {
- </span><span style="color:#0000ff">return</span><span style="color:#000000">; } }
- </span><span style="color:#008000">//</span><span style="color:#008000"> 如果message没有callback,则调用handler的钩子方法handleMessage</span><span style="color:#008000"></span><span style="color:#000000"> handleMessage(msg); } }</span></p>
- 可以看到了吧,在dispatchMessage这个方法内有这么的一句代码:
- <pre><span style="color:#000000"> handleMessage(msg);</span></pre>
- 呵呵呵呵呵呵~~~~~我想现在大家都应该明白了吧,Handler与Looper两者之间的关系和调用。。。。。。<br>
- <p></p>