缓缓飘落的枫叶像思念
当弄明白了Handler机制实现的原理后,自己动手实现一下消息在线程间切换是很简单的事情。
首先我们先来明确一下Handler机制中需要用到的类
- Handler类。Handler类负责关联当前线程的Looper和MessageQueue,以及发送消息到MessageQueue中,还有一个消息处理的回调。
public class MyHandler {
private MyMessageQueue messageQueue;
// 获取Looper与消息队列
public MyHandler(){
MyLooper myLooper = MyLooper.myLooper();
messageQueue = myLooper.getMessageQueue();
}
// 分发消息
public void dispatchMessage(MyMessage msg){
handleMessage(msg);
}
// 发送消息
public void sendMessage(MyMessage message) {
// 将当前的Handler对象赋值给了message的target,
message.target = this;
messageQueue.addMessage(message);
}
public void handleMessage(MyMessage msg) { }
}
- Looper有两个最主要的方法,prepare()和loop()。prepare()方法创建了一个Looper对象,并存入ThreadLocal对象中。loop()从消息队列中不停的取出Message,通过Message.target回调给处理的Handler。此外,Looper还创建了MessageQueue,以及MessageQueue的获取方式。
public class MyLooper {
private static ThreadLocal<MyLooper> threadLocal = new ThreadLocal<>();
public static MyMessageQueue messageQueue;
private MyLooper(){
messageQueue = new MyMessageQueue();
}
public MyMessageQueue getMessageQueue(){
return messageQueue;
}
/**
* 获取当前线程的looper
*/
public static MyLooper myLooper(){
MyLooper myLooper = threadLocal.get();
return myLooper;
}
// 给当前线程创建一个相关联的Looper对象,并存在ThreadLocal当中
public static void prepare(){
if(threadLocal.get() != null){
throw new RuntimeException("Current Thread is created looper");
}else{
threadLocal.set(new MyLooper());
}
}
public static void loop(){
MyLooper myLooper = threadLocal.get();
while(true){
List<MyMessage> msgList = myLooper.messageQueue.getMsgList();
for(int i = 0; i < msgList.size(); i++){
MyMessage myMessage = msgList.get(i);
myMessage.target.dispatchMessage(myMessage);
msgList.remove(msgList.get(i));
}
}
}
}
- Message类就很简单了。只有一个Handler类型的引用,然后what和存储数据的obj。
public class MyMessage {
public MyHandler target;
public int what;
public Object obj;
}
- MessageQueue中也只是维护了一个队列。、
public class MyMessageQueue {
private List<MyMessage> msgList = new ArrayList<MyMessage>();
public void addMessage(MyMessage msg){
msgList.add(msg);
}
public List<MyMessage> getMsgList(){
return msgList;
}
}
- 测试
public class MainActivity extends AppCompatActivity {
private MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
MyLooper.prepare();
mHandler = new MyHandler(){
@Override
public void handleMessage(@NonNull MyMessage msg) {
if(msg.what == 0x111){
Log.e("thread1",msg.obj.toString() );
}
}
};
MyLooper.loop();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
MyMessage message = new MyMessage();
message.what = 0x111;
message.obj = "哎呀妈呀,都特么开始手写Handler了,牛逼牛逼!";
mHandler.sendMessage(message);
try{
Thread.sleep(2000);
}catch (Exception ee){
ee.printStackTrace();
}
}
});
thread1.start();
try{
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
thread2.start();
}
}
image.png
测试后,可以看到消息确实是从thread2发送给了thread1。手写Handler完美成功。
但是我们这里有一个问题,就是Thread1收到一次消息后,如果再在Thread2里面发送一次消息,Thread1就收不到消息了。因为Thread1的线程已经执行完了,Handler对象也就被销毁了。
我们平常用的Handler都是接收了一个消息之后,还是可以继续接收的。因为我们创建Handler的时候是在主线程创建的,而主线程是一直运行的,不会死掉的,直到我们退出APP。
网友评论