Android异步通信机制(一)

简单地理解,Handler是当前线程的消息队列中的一个子队列,而Runable是可以被安排到Handler去运行的接口。

 

首先在Activity中创建一个继承自Handler的匿名内部类以及这个类的一个对象

Private MainHandler mMainHandler = new MainHandler();

private class MainHandler extends Handler {

    public void handleMessage(android.os.Message msg) {

         switch (msg.what) {

         case MSG_MAIN_HANDLER_TEST:

              Log.d(TAG, "handleMessage-->thread id = " +                             

              Thread.currentThread().getId());

              break;

         }

    }

 };

这样在Activity的其他地方就可以通过mMainHandler对象发送消息给Handler处理了

Message msg = mMainHandler.obtainMessage(MSG_MAIN_HANDLER_TEST);

         mMainHandler.sendMessage(msg);

Handler处理runnables方法中的代码

使用Handler发送以及处理消息外,handler还有一个作用就是处理传递给它的action对象,具体使用步骤示例:

1、在主线程中定义Handler对象

2、构造一个runnable对象,为该对象实现runnable方法。

3、在子线程中使用Handler对象post(runnable)对象.

 

handler.post这个函数的作用是把Runnable里面的run方法的这段代码发送到消息队列中,等待运行。
如果handler是以UI线程消息队列为参数构造的,那么是把run里面的代码发送到UI线程中,等待UI线程运行这段代码。如果handler是以子线程线程消息队列为参数构造的,那么是把run里面的代码发送到子线程中,等待子线程运行这段代码。

 

Runnable本身并不是一个线程,只是接口,但是这个接口可以在别的线程中运行

 

public class TestActivity extends Activity implements OnClickListener {

     private Button mBtnTest=null;

     private Handler myHandler=null;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

       

        mBtnTest=(Button)findViewById(R.id.btn_test);

        mBtnTest.setOnClickListener(this);       

        myHandler=new Handler();

    }

     @Override

     public void onClick(View v) {

         //注意:此处UI线程被阻塞,因为myHandler是在UI线程中创建的

         myHandler.post(new Runnable() {

              public void run() {

                   long i=0;

                  while(true){

                  i++;

                  }

                   }

              });

     }

}

这里我们看代码 mHandler.post(new Runnable(){  好像是new 了一个 interface,其实是new的一个实现Runnable的匿名内部类(Inner Anonymous Class),这是很简练的写法。

上面的代码可以看成是: new anonymousClass() implement interface{ [改写interface method]}

Runnable是一个接口,不是一个线程,一般线程会实现Runnable。所以如果我们使用匿名内部类是运行在UI主线程的,如果我们使用实现这个Runnable接口的线程类,则是运行在对应线程的。

而Android应用程序是消息驱动的。Android通过Looper、Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环)。

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个 Looper的同时,会创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。

这样说来,多个Handler都可以共享同一Looper和MessageQueue了。当然,这些Handler也就运行在同一个线程里。

如何实现消息的发送与处理

接下来,我们简单地看一下消息的循环过程:

A消息的生成

       Message msg = mHandler.obtainMessage();

       msg.what = what;

       msg.sendToTarget();

B消息的发送

       MessageQueue queue = mQueue;

        if (queue != null) {

            msg.target = this;

            sent = queue.enqueueMessage(msg, uptimeMillis);

        }

在Handler.java 的sendMessageAtTime(Message msg, long uptimeMillis)方法中,我们看到,它找到它所引用的MessageQueue,然后将Message的target设定成自己(目的是为了在处理消息环节,Message能找到正确的Handler),再将这个Message纳入到消息队列中。

C消息的抽取

        Looper me = myLooper();

        MessageQueue queue = me.mQueue;

        while (true) {

            Message msg = queue.next(); // might block

            if (msg != null) {

                if (msg.target == null) {

                    // No target is a magic identifier for the quit message.

                    return;

                }

                msg.target.dispatchMessage(msg);

                msg.recycle();

            }

        }

在Looper.java 的loop()函数里,我们看到,这里有一个死循环,不断地从MessageQueue中获取下一个(next方法)Message,然后通过Message中携带的target信息,交由正确的Handler处理(dispatchMessage方法)。

D消息的处理

        if (msg.callback != null) {

            handleCallback(msg);

        } else {

            if (mCallback != null) {

                if (mCallback.handleMessage(msg)) {

                    return;

                }

            }

            handleMessage(msg);

        }

在Handler.java的dispatchMessage(Message msg)方法里,其中的一个分支就是调用handleMessage方法来处理这条Message,而这也正是我们在职责处描述使用Handler时需要实现handleMessage(Message msg)的原因。

一个Message经由Handler的发送,MessageQueue的入队,Looper的抽取,又再一次地回到Handler的怀抱。而绕的这一圈,也正好帮助我们将同步操作变成了异步操作。

你可能感兴趣的:(android,UI,null,Class,button,interface)