简单地理解,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的怀抱。而绕的这一圈,也正好帮助我们将同步操作变成了异步操作。

更多相关文章

  1. Android源码解析之(三)Android异步任务AsyncTask
  2. 【转】备份:Android(安卓)常用 mimeType 表
  3. 文件接收网络对讲机C#服务器 Android客户端(二) C#服务器代码分析
  4. 备份:Android(安卓)常用 mimeType 表
  5. 2019 Android开发工程师面经
  6. Android(安卓)中状态栏(屏幕顶部)消息的显示 Notification
  7. android 定时器 总结
  8. 关于使用腾讯云腾讯(即时通讯SDK)遇到的问题
  9. Android(安卓)中文 API (101) —— AsyncTask

随机推荐

  1. android的互联网开发 下
  2. Android左右滑动菜单
  3. Android- Button Transparent
  4. android 网络状态监听
  5. Android(安卓)Recyclerview 滚动事件监听
  6. 在Android中创建文件
  7. android相机camera拍照
  8. android wifi porting
  9. Android(安卓)Studio 无法编译,出现下列错
  10. android常用类