您的位置:首页 > 移动开发 > Android开发

自己动手写消息机制

2016-07-21 11:25 525 查看
首先,我们先别管Android中的消息机制,我们先来看一个需求:

在主线程中启动一个子线程去做一些事情,我希望子线程在做完这些事情后唤醒主线程来做一些相应的动作。

先想想怎么实现这个功能。直接在子线程回调一个接口?显然不行!

要让主线程感知到子线程的事情是否做完了。一般来说,就是在子线程完成事情后发送一些消息给主线程,让主线程知道子线程已经完成了工作,然后主线程去做相应的处理。这样一来,主线程就要变成一个死循环,无限循环的从消息队列中获取从子线程来的消息,并处理。



图中,主线程是一个轮询线程,主线程要做的事情就是,不断从消息队列中获取消息,并做处理。子线程处理完相关的业务之后,发送一个消息到消息队列中。整个过程是异步的。

同步:主线程启动一个子线程,在子线程执行过程中,主线程等待子线程完成后才继续往下运行

异步:主线程启动一个子线程,在子线程执行过程中,主线程也在运行

我们建立一个Java项目,简单模仿一下Android的消息机制



Looper是用来将线程变成一个轮询线程

package com.zhanjixun;

import java.util.HashMap;
import java.util.Map;

public class Looper {

private static Map<Long, Looper> mLoopers = new HashMap<Long, Looper>();

private MessageQueue mQueue = new MessageQueue();

private Looper() {

}

public static void prepare() {
long id = Thread.currentThread().getId();
if (mLoopers.get(id) != null) {
throw new RuntimeException("这线程的Looper已经调用prepare()");
}
mLoopers.put(id, new Looper());
}

public static void loop() {
while (true) {
Message next = myLooper().getMessageQueue().next();
if (next != null) {
if (next.getTarget() == null) {
return;
} else {
next.getTarget().handlerMessage(next);
}
}
}
}

public static Looper myLooper() {
Looper looper = mLoopers.get(Thread.currentThread().getId());
if (looper == null) {
throw new RuntimeException(Thread.currentThread().getName()
+ "线程的Looper还没有调用prepare()");
}
return looper;
}

public MessageQueue getMessageQueue() {
return mQueue;
}
}


其中的MessageQueue是用来管理Message的队列数据结构,先进先出原则

package com.zhanjixun;

import java.util.LinkedList;

public class MessageQueue {

private LinkedList<Message> mMsgs = new LinkedList<>();

public void push(Message msg) {
System.out.println("有消息进队列-->>>" + msg.toString());
mMsgs.add(msg);
}

public Message next() {
if (mMsgs.size() > 0) {
Message removeFirst = mMsgs.removeFirst();
System.out.println("有消息从队列被取出<<<---" + removeFirst.toString());
return removeFirst;
}
return null;
}

}
Message类是对要发送的消息的一个封装

package com.zhanjixun;

public class Message {
public int what;
public Object obj;
private Handler target;

public Handler getTarget() {
return target;
}

public void setTarget(Handler target) {
this.target = target;
}

}


Handler负责发送Message以及轮询线程回调

package com.zhanjixun;

/**
* Handler负责发送Message以及轮询线程回调
*
* @author doudian
*
*/
public class Handler {

private Looper myLooper;

/**
* 创建Handler一定要在轮询线程中创建,因为创建的时候需要获取轮询线程的Looper
*/
public Handler() {
myLooper = Looper.myLooper();
}

public void sendMessage(Message message) {
message.setTarget(this);
myLooper.getMessageQueue().push(message);
}

public void handlerMessage(Message message) {

}
}


最后在Main方法中调用试试看成果

package com.zhanjixun;

public class Main {

public static void main(String[] args) {
Looper.prepare();
Handler handler = new Handler() {
@Override
public void handlerMessage() {
System.out.println(" doing something in "
+ Thread.currentThread().getName() + " thread");
}
};
new Thread(new Runnable() {

@Override
public void run() {
System.out.println(" doing something in "
+ Thread.currentThread().getName() + " thread");
handler.sendMessage(new Message());
}
}).start();
Looper.loop();
throw new RuntimeException("主线程不小心停止了!");
}
}


运行结果



源代码:http://download.csdn.net/detail/zhanjixun/9582075

写到这里大概就能明白整个消息机制的原理了:就是将主线程(也可以是其他子线程)变成一个死循环的线程,不断从队列中获取消息并处理;子线程处理一些业务,处理完毕就发送一个消息到消息队列中。

有空在分析一下Android中消息机制的源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息