您的位置:首页 > 产品设计 > UI/UE

Android异步消息处理之Looper,Handler,Message,MessageQueue

2016-05-29 10:19 375 查看
android为我们提供了很多办法。

1)、handler和message机制:通过显示的抛出、捕获消息与ui进行交互;

2)、Activity.runOnUiThread(Runnable):如果当前线程为ui线程,则立即执行;否则,将参数中的线程操作放入到ui线程的事件队列中,等待执行。

3)、View.post(Runnable):将操作放入到message队列中,如果放入成功,该操作将会在ui线程中执行,并返回true,否则返回false

4)、View.postDelayed(Runnable, long)跟第三条基本一样,只不过添加了一个延迟时间。

5)、android1.5以后为我们提供了一个工具类来搞定这个问题AsyncTask.

异步消息线程不同一般线程的是,它的线程run方法有一个无限循环,每循环一次,从其内部的消息队列中取出一个消息并调用回调函数进行处理。如果消息队列为空,线程暂停,直到消息队列中有新的消息。

(一)Looper,Handler,Message,MessageQueue

1、 Looper主要作用就是产生及管理MessageQueue,Looper是整个消息循环的基础。某个线程调用Looper的prepare方法时,prepare方法内部会生成一个MessageQueue,而且一个线程最多只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。在主线程使用Handler时不需要调用Looper.prepare(),Looper.loop(),因为主线程的main()方法中已经调用 Looper.prepareMainLooper()来产生了一个MessageQueue,同时调用了Looper.loop()来进行循环处理。但是在非主线程使用Handler则必须要调用这两个方法。

2、 调用looper的loop()方法时,loop()方法内部会不断从MessageQueue中去取Message,同时调用Handler 的dispatchMessage方法把消息交给Handler处理。

3、 Handler的作用一是把Message发送到MessageQueue中,二是处理MessageQueue中的Message(由Looper从MessageQueue中取出Message交给Handler处理)。

4、 Message 代表一个行为(what)或者一串动作(Runnable)

5、 每个线程可以包含多个Handler,Handler将Message发送到MessageQueue中,调用sendMessage方法,其内部又调用enqueueMessage方法将Message加入到MessageQueue中。而enqueueMessage将此Handler赋值给Message的target变量,这也就将Message与Handler绑定在一起了,因为是哪儿Handler发送的Message就由哪个Handler处理,也就是由创建Handler的线程处理。

6 、 Messenger可以翻译为信使,可以实现进程间通信(IPC),Messenger采用一个单线程来处理所有的消息,而且进程间的通信都是通过发消息来完成的,感觉不能像AIDL那样直接调用对方的接口方法(具体有待考证),这是其和AIDL的主要区别,也就是说Messenger无法处理多线程,所有的调用都是在一个线程中串行执行的。Messenger的典型代码是这样的:new Messenger(service).send(msg),它的本质还是调用了Handler的sendMessage方法
4000

下面是Looper的主要代码片段:

public final class Looper {
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;  // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;

public static void prepare() {
prepare(true);
}

private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}

public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;

// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();

for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
。。。省略
msg.target.dispatchMessage(msg);//msg.target就是Handler
。。。省略
}
}


下面是Message的部分代码:

public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;

public Messenger replyTo;
int flags;
long when;
Bundle data;
Handler target;
Runnable callback;
Message next;
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
}


下面是Handler的部分代码:

final MessageQueue mQueue;
final Looper mLooper;
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
。。。省略

mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}

public void dispatchMessage(Message msg) {
if (msg.callback != null) {//msg.callback是Runnable对象, 直接调用msg.callback.run();
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}


Handler的post()方法

View的post()方法

Activity的runOnUiThread()方法

我们先来看下Handler中的post()方法,代码如下所示:

public final boolean post(Runnable r)
{
return  sendMessageDelayed(getPostMessage(r), 0);
}


原来这里还是调用了sendMessageDelayed()方法去发送一条消息啊,并且还使用了getPostMessage()方法将Runnable对象转换成了一条消息,我们来看下这个方法的源码:

private final Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}


在这个方法中将消息的callback字段的值指定为传入的Runnable对象。咦?这个callback字段看起来有些眼熟啊,喔!在Handler的dispatchMessage()方法中原来有做一个检查,如果Message的callback等于null才会去调用handleMessage()方法,否则就调用handleCallback()方法。那我们快来看下handleCallback()方法中的代码吧:

private final void handleCallback(Message message) {
message.callback.run();
}


也太简单了!竟然就是直接调用了一开始传入的Runnable对象的run()方法。因此在子线程中通过Handler的post()方法进行UI操作就可以这么写:

public class MainActivity extends Activity {

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
// 在这里进行UI操作
}
});
}
}).start();
}
}


虽然写法上相差很多,但是原理是完全一样的,我们在Runnable对象的run()方法里更新UI,效果完全等同于在handleMessage()方法中更新UI。

然后再来看一下View中的post()方法,代码如下所示:

public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}


原来就是调用了Handler中的post()方法,我相信已经没有什么必要再做解释了。

最后再来看一下Activity中的runOnUiThread()方法,代码如下所示:

public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}


如果当前的线程不等于UI线程(主线程),就去调用Handler的post()方法,否则就直接调用Runnable对象的run()方法。还有什么会比这更清晰明了的吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: