Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)

前言

最近刚好在做关于异步通信的需求,那么,今天我们来讲解下Android开发中的Handler异步通信传递机制(包括Looper、Message Queue)


目录

Handler.png


定义

Android提供的一套消息传递机制


作用

用于实现子线程对UI线程的更新,实现异步消息的处理:

  • 在新启动的线程中发送消息
  • 在主线程中获取并处理信息

为什么要用Handler

在安卓开发中:

  • 为了保证Android的UI操作是线程安全的,Android规定了只允许UI线程修改Activity里的UI组件;
  • 但在实际开发中,必然会用到多个线程并发操作UI组件,这又将导致UI操作的线程不安全

所以问题在于:如何同时满足:

  • 保证线程安全
  • 使多个线程并发操作UI组件

Handler消息传递机制就是这个问题的。


相关概念

主线程(UI线程)

  • 定义:当程序第一次启动时,Android会同时启动一条主线程(Main Thread)
  • 作用:主线程主要负责处理与UI相关的事件,所以主线程又叫UI线程

    子线程则负责一些比较耗时的操作(联网、取数据、SD卡数据加载等操作),而主线程和子线程之间的通信,就是要靠Handler了。

Message

  • 定义:消息,理解为线程间通讯的数据单元(Handler接受和处理的消息对象。)

    例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程

Message Queue

  • 定义:消息队列
  • 作用:用来存放通过Handler发过来的消息,按照先进先出执行

Handler

  • 定义:Handler是Message的主要处理者
  • 作用:负责将Message添加到消息队列&处理Looper分派过来的Message

Looper

  • 定义:循环器,扮演Message Queue和Handler之间桥梁的角色

  • 作用:主要负责消息循环:循环取出Message Queue的Message;消息派发:将取出的Message交付给相应的Handler

    1. 每个线程中只能拥有一个Looper,但是一个Looper可以和多个线程的Handler绑定起来,也就是说很多个线程可以往一个Looper所持有的MessageQueue中发送消息。这就给我们提供了线程之间通信的可能。
    2. Handler在创建的时候可以显示指定Looper,这样在Handler在调用sendMessage()投递消息的时候会将消息添加到指定的Looper里面的MessageQueue。如果不指定Looper,Handler默认绑定的是创建它的线程的Looper。

Handler异步通信机制工作流程图

Handler异步通信传递机制流程图


Handler、Looper、MessageQueue关系类图

Handler、Looper、MessageQueue关系类图.png

Handler

  • 提供sendMessage方法,将消息放置到队列中
  • 提供handleMessage方法,定义个各种消息的处理方式;

Looper

  • Looper.prepare():实例化Looper对象;为当前线程生成一个消息队列;
  • Looper.loop() :循环从消息队列中获取消息,交给Handler处理;此时线程处于无限循环中,不停的从MessageQueue中获取Message 消息 ;如果没有消息就阻塞

MessageQueue

  • 提供enqueueMessage 方法,将消息根据时间放置到队列中;
  • 提供next方法,从队列中获取消息,没有消息的时候阻塞;

Handler工作流程解释
异步通信传递机制步骤主要包括异步通信的准备、消息发送、消息循环和消息处理

  1. 异步通信的准备
    包括Looper对象的创建&实例化、MessageQueue队列的创建和Handler的实例化
  2. 消息发送
    Handler将消息发送到消息队列中
  3. 消息循环
    Looper执行Looper.loop()进入消息循环,在这个循环过程中,不断从该Message Queue取出消息,并将取出的消息派发给创建该消息的Handler
  4. 消息处理
    调用该Handler的dispatchMessage(msg)方法,即回调handleMessage(msg)处理消息

好像很复杂?那就先看下这个简图了解下:

page3.png


工作流程详细讲解

由上面可以得知,整个异步消息传递机制主要包括Handler、Looper和MessageQueue,接下来通过相应源码来解析这三部分

第一部分:Looper

Looper主要负责:

  1. 自身的创建&创建Message Queue
  2. 消息循环(消息取出、派发)

对应职责我们来看下相应的源码:

  1. 自身的创建&创建Message Queue:prepare()方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public static final void prepare() {
    //判断sThreadLocal是否为null,否则抛出异常
    //即Looper.prepare()方法不能被调用两次
    //也就是说,一个线程中只能对应一个Looper实例
    if (sThreadLocal.get() != null) {
    throw new RuntimeException("Only one Looper may be created per thread");
    }
    //sThreadLocal是一个ThreadLocal对象,用于在一个线程中存储变量
    //实例化Looper对象并存放在ThreadLocal
    //这说明Looper是存放在Thread线程里的
    sThreadLocal.set(new Looper(true));
    }
    //再来看下Looper的构造方法
    private Looper(boolean quitAllowed) {
    //创建了一个MessageQueue(消息队列)
    //这说明,当创建一个Looper实例时,会自动创建一个与之配对的MessageQueue(消息队列)
    mQueue = new MessageQueue(quitAllowed);
    mRun = true;
    mThread = Thread.currentThread();
    }

2. 消息循环:loop()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public static void loop() {
//myLooper()方法作用是返回sThreadLocal存储的Looper实例,如果me为null,loop()则抛出异常
//也就是说loop方法的执行必须在prepare方法之后运行
//也就是说,消息循环必须要先在线程当中创建Looper实例
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取looper实例中的mQueue(消息队列)
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
//进入消息循环
for (;;) {
//next()方法用于取出消息队列里的消息
//如果取出的消息为空,则线程阻塞
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//消息派发:把消息派发给msg的target属性,然后用dispatchMessage方法去处理
//Msg的target其实就是handler对象,下面会继续分析
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "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);
}
//释放消息占据的资源
msg.recycle();
}
}

总结Looper的作用:

  1. 实例化本身、与当前线程绑定、创建与之相应的MessageQueue:prepare()方法

    一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue

  2. 消息循环(消息取出、消息派发):loop()方法
    不断从MessageQueue中去取消息,派发给消息的target属性的Handler,然后调用相应Handler的dispatchMessage()方法进行消息处理。


第二部分:Handler

主要负责:

  1. 在子线程发送消息给MessageQueue
  2. 处理Looper派发过来的消息

使用Handler之前,会初始化一个Handler实例

Handler是需要和线程绑定在一起的,在初始化Handler的时候一般通过指定Looper对象从而绑定相应线程,即给Handler指定Looper对象=绑定到了Looper对象所在的线程中,Handler的消息处理回调会在那个线程中执行。一般有两种方法创建:

  1. 通过Loop.myLooper()得到当前线程的Looper对象/通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。
  2. 不指定Looper对象,那么这个Handler绑定到了创建这个线程的线程上,消息处理回调也就在创建线程中执行.

首先看Handler的构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
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());
}
}
//通过Looper.myLooper()获取了当前线程保存的Looper实例,如果线程没有Looper实例那么会抛出异常
//这说明在一个没有创建Looper的线程中是无法创建一个Handler对象的
//所以说我们在子线程中创建一个Handler时首先需要创建Looper,并且开启消息循环才能够使用这个Handler。
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//获取了这个Looper实例中保存的MessageQueue(消息队列)
//这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}

  • 上述说明:当Handler初始化时,可通过构造方法自动关联Looper和相应的MessageQueue

1. Handler向MessageQueue发送消息:对于Handler的发送方式可以分为post和send两种方式。

send的发送方法:sendMessage()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
//我们往下扒
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//直接获取MessageQueue
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
//调用了enqueueMessage方法
return enqueueMessage(queue, msg, uptimeMillis);
}
//调用sendMessage方法其实最后是调用了enqueueMessage方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//为msg.target赋值为this,也就是把当前的handler作为msg的target属性
//如果大家还记得Looper的loop()方法会取出每个msg然后执行msg.target.dispatchMessage(msg)去处理消息,其实就是派发给相应的Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//最终调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去。
return queue.enqueueMessage(msg, uptimeMillis);
}

Post的发送方法:sendMessage()

1
2
3
4
5
6
7
8
showhandler.post(new Runnable() {
@Override
public void run() {
String line = "\n";
StringBuffer text = new StringBuffer(show.getText());
text.append(line).append("angelababy:Yes,I do");
show.setText(text);
}

  • 相比send方法,post方法最大的不同在于,更新UI操作可直接在重写的run方法定义。
  • 其实Runnable并没有创建什么线程,而是发送了一条消息,下面看源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
//创建了一个Message对象
//创建Message对象可以new,也可以使用Message.obtain()方法;
//但是更建议使用obtain方法,因为Message内部维护了一个Message池用于Message的复用,避免使用new 重新分配内存。
Message m = Message.obtain();
//将我们创建的Runable对象作为callback属性,赋值给了此message.
m.callback = r;
//创建了一个Message对象
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
  • 从上面的源码发现了吧?和send中的handler.sendMessage是一样的。

    调用了sendMessageAtTime,然后调用了enqueueMessage方法,给msg.target赋值为handler,最终Handler将消息加入MessagQueue.

  • 但是细心的你会发现,在使用Post方法时会将我们创建的Runable对象作为callback属性赋值给了此message
    那么msg的callback和target都有值,那么会执行哪个呢?
    我们已知回调发送消息的方法是:dispatchMessage()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public void dispatchMessage(Message msg) {
    //一开始就会进行判断
    //如果msg.callback属性不为null,则执行callback回调,也就是我们的Runnable对象
    if (msg.callback != null) {
    handleCallback(msg);
    } else {
    if (mCallback != null) {
    if (mCallback.handleMessage(msg)) {
    return;
    }
    }
    handleMessage(msg);
    }
    }

    ####2. 处理Looper派发过来的消息:dispathMessage()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public void handleMessage(Message msg) {
}
  • 可以看到dispathMessage()方法里调用了 handleMessage()方法,但handleMessage()是一个空方法
  • 因为Handler发送消息过来是希望进行一定的处理,至于怎么处理消息是该Handler最终控制的,所以我们在创建handler时需要通过复写handleMessage()方法从而实现我们需要的消息处理方式,然后根据msg.what标识进行消息处理。

这就是为什么我们在主线程中实例化Handler的时候需要重写handleMessage()

特别注意

在一个Android应用启动的时候,会创建一个主线程,即ActivityThread(也叫UI线程),在ActivityThread中有一个静态的main方法:应用程序的入口点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//一个进程会默认生成一个主线程
public static void main(String[] args) {
......
//主线程生成时自动通过prepareMainLooper方法为主线程创建一个Looper
//prepare()方法是用于在子线程中创建一个Looper对象,在子线程中是可以退出消息循环的:调用消息队列的quit方法
//Looper生成时会自动生成与之配套的消息队列
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
......
//loop()方法开启消息循环
//主线程的消息循环是不允许被退出的
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

第三部分:MessageQueue

即消息队列,用于存放Handler发送过来的消息

为了提高插入删除的效率,采用单链表的方式实现。

对于MessageQueue,我们来看下入队和出队操作

MessageQueue入队

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
boolean enqueueMessage(Message msg, long when) {
......
synchronized (this) {
......
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}

消息的入队(插入)过程

  • 首先判断消息队列里有没有消息,没有的话则将当前插入的消息作为队头,并且这时消息队列如果处于等待状态的话则将其唤醒。
  • 若是在中间插入,则根据Message创建的时间进行插入。

MessageQueue出队

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Message next() {
......
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// nativePollOnce方法在native层,若是nextPollTimeoutMillis为-1,这时候消息队列处于等待状态。   
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
//按照我们设置的时间取出消息
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// 如果消息队列中没有消息,将nextPollTimeoutMillis设为-1,下次循环消息队列则处于等待状态
nextPollTimeoutMillis = -1;
}
//退出消息队列,返回null,这时候Looper中的消息循环也会终止。 
if (mQuitting) {
dispose();
return null;
}
......
}
.....
}
}

Thread、Looper、Handler之间的对应关系:

  • 一个Thread(线程)只能有一个Looper,可以有多个Handler
  • 一个Looper可以绑定多个Handler;
  • 一个Handler只能绑定一个Looper;

对应关系.png


回顾工作原理图

把Handler工作原理都讲解完了,我们再来看下一开始说的工作原理图,你大概会有更深的理解了。
Handler异步通信传递机制流程图


实例

没有实际应用的博客都不是好博客!现在是时候看一下实际应用了

Demo的源码下载

https://github.com/Carson-Ho/Handler_learning
(个人推荐先fork下来再对着下面的分析看,效果会更好哦!)

  1. 布局文件:
    activity_main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.carson_ho.handlerdemo.MainActivity">
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
</RelativeLayout>

2. 1 send方法:MainActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.example.carson_ho.handlerdemo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView show;
private Handler showhandler;
@Override
//主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (TextView) findViewById(R.id.show);
//实例化Handler,这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
showhandler = new FHandler();
//启动子线程
new Thread_1().start();
new Thread_2().start();
}
class FHandler extends Handler{
//通过复写handlerMessage()从而决定如何进行更新UI操作
@Override
public void handleMessage(Message msg) {
StringBuffer text = new StringBuffer();
switch (msg.what) {
case 1:
text.append("I love Carson_Ho");
show.setText(text);
break;
case 2:
text.append("I hate Carson_Ho");
show.setText(text);
break;
}
}
}
class Thread_1 extends Thread {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//定义要发送的消息
Message msg = Message.obtain();
msg.what = 1;//用于消息的标识
msg.obj = "AA";//用于消息的存放
//传入主线程的Handler并其MessageQueue发送消息
showhandler.sendMessage(msg);
}
}
class Thread_2 extends Thread {
@Override
public void run() {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = Message.obtain();
msg.what = 2;
msg.obj = "BB";
showhandler.sendMessage(msg);
}
}
}

2. 2 Post方法:MainActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.example.carson_ho.handlerdemo;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public TextView show;
public Handler showhandler;
@Override
//主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (TextView) findViewById(R.id.AA);
StringBuffer text = new StringBuffer();
text.append("Carson_Ho:Do you love me?");
show.setText(text);
//实例化Handler,这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
showhandler = new Handler();
//启动子线程
new Thread_1().start();
new Thread_2().start();
}
class Thread_1 extends Thread {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
showhandler.post(new Runnable() {
@Override
public void run() {
String line = "\n";
StringBuffer text = new StringBuffer(show.getText());
text.append(line).append("angelababy:Yes,I do");
show.setText(text);
}
});
}
}
class Thread_2 extends Thread {
@Override
public void run() {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
showhandler.post(new Runnable() {
@Override
public void run() {
String line = "\n";
StringBuffer text = new StringBuffer(show.getText());
text.append(line).append("黄晓明:what the fuck?");
show.setText(text);
}
});
}
}
}

Demo的源码下载

https://github.com/Carson-Ho/Handler_learning


参考文献
http://blog.csdn.net/lmj623565791/article/details/38377229

总结

本文对Handler异步通信机制全面解析(包含Looper、Message Queue)进行了全面介绍和分析,接下来我会介绍继续介绍Android开发中的相关知识,有兴趣可以继续关注[Carson_Ho的安卓开发笔记]

文章目录
  1. 1. 前言
    1. 1.1. 目录
  2. 2. 定义
  3. 3. 作用
  4. 4. 为什么要用Handler
  5. 5. 相关概念
  6. 6. Handler异步通信机制工作流程图
  7. 7. Handler、Looper、MessageQueue关系类图
  8. 8. 工作流程详细讲解
    1. 8.0.0.1. 第一部分:Looper
  • 8.1. 第二部分:Handler
    1. 8.1.0.1. 1. Handler向MessageQueue发送消息:对于Handler的发送方式可以分为post和send两种方式。
  • 8.1.1. 特别注意
    1. 8.1.1.1. 第三部分:MessageQueue
  • 9. Thread、Looper、Handler之间的对应关系:
  • 10. 回顾工作原理图
  • 11. 实例
    1. 11.0.0.1. Demo的源码下载
  • 12. Demo的源码下载
  • 13. 总结
  • ,