Android开发总结笔记 消息处理机制 5-1
来源:互联网 发布:网络信息员 编辑:程序博客网 时间:2024/05/16 09:48
参考:http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
Android的消息处理机制有三个核心的类
Looper
Handler
Message
事实上还有另外一个Message Queue消息队列,不过被封装到Looper中了
Looper
Looper用来将一个普通线程变成一个Looper线程
其中用到了两个方法
Looper.prepare()
Looper.loop()
来看一下源码中这两个方法是怎么运作的。
1)Looper.prepare()
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
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));
}
可以看到内部维护了一个MesssageQueue,这里涉及到了一个变量,ThreadLocal是一个线程的局部变量
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
这也是为什么一个Thread只能有一个Looper对象的原因。
2)Looper.loop()
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
可以看到,如果没有执行Looper.prepare,me就不会被赋值,从而抛出异常
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;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
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.recycleUnchecked();
}
}
从第13开始看起,利用一个死循环从MessageQuene里面不断地取出Message
在24行把真正的处理工作分发给Message的target,也就是Handler
Handler
Looper负责从MessageQueue中拿出消息。
那么就需要有一个可以往MessageQueue添加的消息的工具,这个工具就是Handler
除了添加消息之外,Handler还能处理消息,仅限于处理自己发出的消息
先来看看添加消息的
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());
}
}
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;
}
在11行和16行可以看出,将Looper中的ThreadLocal和消息队列关联到Handler
创建了Handler对象之后,可以利用以上的各种postXX和sendXX方法来发送消息到MesssageQueue
可以看到post发出的是Runnable,而send发出的是Message,
但是到最后,post发出的Runnable都会被封装成Message
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
下面就是处理消息的
在上面的Looper中,有一段
msg.target.dispatchMessage(msg);
这个是Handler的方法,负责处理消息,来看一下这个方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到这里调用了接口的方法,让子类去实现
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
所以,只需要new出一个Handler,并实现handleMessage方法,就可以使用了
private static void handleCallback(Message message) {
message.callback.run();
}
Message
Message就是用来携带信息的一类
Message message = Message.obtain();
message.arg1 = 1;
message.arg2 = 2;
message.obj = "Demo";
message.what = 3;
Bundle bundleData = new Bundle();
bundleData.putString("Name", "Lucy");
message.setData(bundleData);
Message.obtain用于获取一个Message对象
后面就是一些携带的信息
- Android开发总结笔记 消息处理机制 5-1
- Android异步消息处理机制总结笔记
- Android消息处理机制笔记
- android消息传递与处理机制总结
- Android异步消息处理机制总结
- Android消息处理机制认识过程总结
- Android消息处理机制深度解析笔记
- Android笔记之消息处理机制
- Android学习笔记--消息处理机制
- Android笔记----AsyncTask异步消息处理机制
- Android的异步消息处理机制笔记
- Android异步消息处理机制学习笔记
- Android开发之消息处理机制
- Android开发之异步消息处理机制
- Android的异步消息处理机制---Handler机制总结
- Android消息机制笔记1
- Android应用开发学习笔记之多线程与Handler消息处理机制
- Android 消息处理机制
- Yoshua Bengio等大神传授:26条深度学习经验
- Java日期加减操作
- Ubuntu 下Putty复制
- BZOJ 1997: [Hnoi2010]Planar|2-SAT|二分图染色
- Unicode 与 ANSI 字符串转换
- Android开发总结笔记 消息处理机制 5-1
- Linux下安装svn服务器
- fragment的handler中getActivity空指针问题
- 如何免费下载YouTube视频
- Spring MVC - 开发 Controller的特性与乱码问题
- JDK SDK NDK ANT ADT
- moc文件 如何生成的
- SVD在推荐系统中的应用详解以及算法推导
- java160102DemoB