自己动手写消息机制
2016-07-21 11:25
525 查看
首先,我们先别管Android中的消息机制,我们先来看一个需求:
在主线程中启动一个子线程去做一些事情,我希望子线程在做完这些事情后唤醒主线程来做一些相应的动作。
先想想怎么实现这个功能。直接在子线程回调一个接口?显然不行!
要让主线程感知到子线程的事情是否做完了。一般来说,就是在子线程完成事情后发送一些消息给主线程,让主线程知道子线程已经完成了工作,然后主线程去做相应的处理。这样一来,主线程就要变成一个死循环,无限循环的从消息队列中获取从子线程来的消息,并处理。
图中,主线程是一个轮询线程,主线程要做的事情就是,不断从消息队列中获取消息,并做处理。子线程处理完相关的业务之后,发送一个消息到消息队列中。整个过程是异步的。
同步:主线程启动一个子线程,在子线程执行过程中,主线程等待子线程完成后才继续往下运行
异步:主线程启动一个子线程,在子线程执行过程中,主线程也在运行
我们建立一个Java项目,简单模仿一下Android的消息机制
Looper是用来将线程变成一个轮询线程
其中的MessageQueue是用来管理Message的队列数据结构,先进先出原则
Handler负责发送Message以及轮询线程回调
最后在Main方法中调用试试看成果
运行结果
源代码:http://download.csdn.net/detail/zhanjixun/9582075
写到这里大概就能明白整个消息机制的原理了:就是将主线程(也可以是其他子线程)变成一个死循环的线程,不断从队列中获取消息并处理;子线程处理一些业务,处理完毕就发送一个消息到消息队列中。
有空在分析一下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中消息机制的源码
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories