你的位置:首页 > 操作系统

[操作系统]结合源代码详解android消息模型


Handler是整个消息系统的核心,是Handler向MessageQueue发送的Message,最后Looper也是把消息通知给Handler,所以就从Handler讲起。

一、Handler

Handler的构造函数有很多,但本质差不多:

public Handler() {     this(null, false);   } 

  

public Handler(Callback callback, boolean async) {     //自动绑定当前线程的looper     mLooper = Looper.myLooper();     if (mLooper == null) {       throw new RuntimeException(         "Can't create handler inside thread that has not called Looper.prepare()");//从这可以看出,创建Handler必须有Looper     }     mQueue = mLooper.mQueue; //Looper的MessageQueue     mCallback = callback;   //一个回掉接口     mAsynchronous = async;    } 

这个是创建给定Looper的Handler  :

public Handler(Looper looper, Callback callback, boolean async) {           mLooper = looper;         mQueue = looper.mQueue;         mCallback = callback;         mAsynchronous = async;     }

二、Looper的源代码:

public static Looper myLooper() {     return sThreadLocal.get();   } 

  在一个子线程中创建Looper的一般步骤:(这是我自己写的,不是源代码)

class MyThread extends Thread{     public Handler handler;     public Looper looper;     public void run() {       Looper.prepare();//创建一个looper       looper = Looper.myLooper();       handler = new Handler(){         @Override       public void handleMessage(Message msg) {          System.out.println("currentThread->"+Thread.currentThread());         }       };       Looper.loop();//让消息循环起来     }   } 

  下面就看看Looper.prepare,Looper.loop方法:

public static void prepare() {     prepare(true);   }    private static void prepare(boolean quitAllowed) {     if (sThreadLocal.get() != null) {//sThreadLocal使得线程能够保持各自独立的一个对象。       throw new RuntimeException("Only one Looper may be created per thread");     }     sThreadLocal.set(new Looper(quitAllowed));   } 

  Looper.prepare():

public static void loop() {     final Looper me = myLooper();     if (me == null) {  //如果Looper为空       throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");     }     final MessageQueue queue = me.mQueue;      。。。。     for (;;) {       Message msg = queue.next(); // 循环下一个       if (msg == null) {         // No message indicates that the message queue is quitting.         return;       }        。。。。        msg.target.dispatchMessage(msg); //分发消息,msg.target就是Handler        if (logging != null) {         logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);       }       。。。。        msg.recycle(); //回收msg到msgPool     }   } 

  从这些代码可以看出Looper不断检查MessagePool是否有《==Message,有的话就通过Handler的dispatchMessage(msg)发送出去,利用Handler与外界交互。

3.Message的源代码:

public static Message obtain() {  //得到Message对象     synchronized (sPoolSync) {       if (sPool != null) {         Message m = sPool;         sPool = m.next;         m.next = null;         sPoolSize--;         return m;       }     }     return new Message(); //没有就新建   } 

  handler.obtainMessage()方法:

public final Message obtainMessage()   {     return Message.obtain(this); //通过Message的obtain方法   } 

  

public static Message obtain(Handler h) { //就是这个方法    Message m = obtain(); //最终调用的还是obtain方法    m.target = h;   //target是handler     return m;  } 

  看了上边的源代码,相信你一定对Handler,message,Looper有了一定了解,对编程中常遇到的方法,知道是怎么用的啦。其实学android一定要常看源码,源码很有用。

4.下边就是上代码,实例分析:

<pre name="code" >package com.example.handler_01;  import android.Manifest.permission; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;  public class MainActivity extends Activity implements OnClickListener{    private TextView textView;   private Button button;         private Handler handler = new Handler(new Callback() {//拦截消息          public boolean handleMessage(Message msg) { //截获handler的发送的消息            Toast.makeText(getApplicationContext(), ""+1, 1).show();       //return false;       return false;//若返回true,则证明截获,下面的handleMessage就不会执行!     }   }){     public void handleMessage(Message msg) {       Toast.makeText(getApplicationContext(), ""+2, 1).show();       Person person = (Person)msg.obj;       System.out.println(person.toString());     }   };      private MyRunnable myRunnable=new MyRunnable();      private ImageView imageView;      private int images[]={R.drawable.a1,R.drawable.a2,R.drawable.a3};   private int index;      class MyRunnable implements Runnable{ //不断的更新图片,3张轮换      @Override     public void run() {      index++;      index=index%3; //不断循环      imageView.setImageResource(images[index]);      handler.postDelayed(myRunnable, 1000); //每隔一段时间执行myRunnable      System.out.println("MyRunnable中的线程:"+Thread.currentThread());//运行在当前主线程!     }        }   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);     textView = (TextView) findViewById(R.id.textview);     imageView = (ImageView) findViewById(R.id.imageView1);     button = (Button) findViewById(R.id.button1);     button.setOnClickListener(this);     new Thread(){       @Override       public void run() {         try {           Thread.sleep(2000);           /*Message message = new Message();          message.arg1=88;*/           Message message = handler.obtainMessage();                      Person person = new Person();           person.age=20;           person.name="chaochao";           message.obj=person;           handler.sendMessage(message);//在子线程中向主线程发消息。         } catch (InterruptedException e) {           // TODO Auto-generated catch block           e.printStackTrace();         }                }     }.start();     handler.postDelayed(myRunnable, 1000);   }   @Override   public void onClick(View v) {     switch (v.getId()) {     case R.id.button1:       handler.removeCallbacks(myRunnable);       //handler.sendEmptyMessage(1);       break;      default:       break;     }        }    class Person{     public int age;     public String name;          public String toString() {      return "name="+name+" age="+age;     }   } } 

  布局很简单,就不上代码啦。

运行结果:

图片自己可以随便能一个。。。。

在后边再详细解析Handler的用法。。

转发请注明出处:http://www.cnblogs.com/jycboy/p/handlerjx.html