1.主线程和子线程通过Thread+Handler通讯的一般使用模式(当然在主线程中Thread+Handler
实现异步的过程并没有完全展示出来,因为在主线程启动的时候,程序就自动帮我们完成了一些操作)
2.下面我们看一个在子线程中使用Handler的案例,看他怎么做的(只是放了重要代码)
哎呀,怎么多了两步Looper.prepare()和Looper.loop(),嗯这就是UI线程中隐藏的操作,伙伴们可以试试去掉会报啥错
我就不啰嗦了。接下来我们就跟踪一下Handler和Thread是怎么实现在子线程mHandler.obtainMessage( what,obj).sendToTarget();
/mHandler.sendMessage(msg);发送消息,UI线程public void handleMessage(Message msg){}接收到消息的。
1.work线程调用:mHandler.obtainMessage(SUCCESS_MSG,bitmap).sendToTarget();
2. 调用Message.java类sendToTarget方法
3. 调用Handler.java类的sendMessage方法
4.调用Handler.java类的sendMessageDelayed方法
5.调用Handler.java类的sendMessageAtTime方法
伙伴们发现return中的方法多了一个queue,他是从哪儿来的呢?
看到MessageQueue queue = mQueue;嗯?mQueue又从哪儿来的呢?再看
可以看出mQueue = looper.mQueue原来是Looper类的实例looper调用了Looper类的成员变量mQueue
初始化的,looper实例有哪儿来的?这个时候Looper.prepare();出来了
看looper实例是sThreadLocal.set(new Looper(quitAllowed));这么出来的,原来一开始在初始化Hanler之前就
通过Looper.prepare()实例化并放到了sThreadLocal中了,而在Looper的构造方法中实例化了mQueue,这个时候
mQueue = loopery.mQueue中looper实例和mQueue成员变量都有了吧(先不要管sThreadLocal是啥,就当他是一个Looper
的容器,由上可以看出每个线程对应一个looper实例,每个looper实例对应一个它自己的MessageQueue)
再看Looper.java类中myQueue方法显示通过myLooper().mQueue实现
而myLooper().mQueue刚好就是sThreadLocal.get().mQueue也就是通过Looper.prepare()实例化的looper实例对应的MessageQueue
回到sendMessageAtTime方法继续往下看
6.调用MessageQueue.java类的enqueueMessage方法
这里实现了消息队列的排队与队序管理,哎,伙伴们肯定疑惑,这也没有实现传递数据啊,为啥handleMessage(Message msg) {}
就能接收到数据了呢?好吧别急,我们还没看Looper.loop()呢。
7.调用Looper.java中的loop()方法
从代码中可以看出他依然获取了之前Looper.prepare()中的looper实例和对应的MessageQueue,当然数据信息也在里面,在看到
msg.target.dispatchMessage(msg);中msg.target当然就是目标的Handler了也就是发送数据消息的mHandler,接下来我们看看dispatchMessage(msg)
8.调用Handler.java中的dispatchMessage()方法
Ok,看到了吧,这里调用了Handler.java中的handleMessage(msg)方法,并把数据信息msg传递了过来,当然在UI线程中就可以
通过当前Handler实例对象mHandler重写handleMessage(msg)方法获取数据信息更新UI咯。
ps:该篇文章是本人对Handler+Thread的学习理解,若有不对的地方,希望能指出来,共同进步。
推荐文章: http://blog.youkuaiyun.com/guolin_blog/article/details/9991569
实现异步的过程并没有完全展示出来,因为在主线程启动的时候,程序就自动帮我们完成了一些操作)
Handler mHandler;
mHandler = new Handler(){
//主线程用来接收数据或更新UI
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
//线程用作处理耗时操作
new Thread(new Runnable() {
@Override
public void run() {
/*
与下面效果相同
Message msg = mHandler.obtainMessage();
msg.obj = bitmap;
msg.arg1 = SUCCESS_MSG;
mHandler.sendMessage(msg);
*/
//mHandler主线程的定义的Handler
mHandler.obtainMessage( what,obj).sendToTarget();
}
}).start();
2.下面我们看一个在子线程中使用Handler的案例,看他怎么做的(只是放了重要代码)
private Handler handler;
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}).start();
哎呀,怎么多了两步Looper.prepare()和Looper.loop(),嗯这就是UI线程中隐藏的操作,伙伴们可以试试去掉会报啥错
我就不啰嗦了。接下来我们就跟踪一下Handler和Thread是怎么实现在子线程mHandler.obtainMessage( what,obj).sendToTarget();
/mHandler.sendMessage(msg);发送消息,UI线程public void handleMessage(Message msg){}接收到消息的。
1.work线程调用:mHandler.obtainMessage(SUCCESS_MSG,bitmap).sendToTarget();
2. 调用Message.java类sendToTarget方法
public void sendToTarget() {
target.sendMessage(this);
}
3. 调用Handler.java类的sendMessage方法
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
4.调用Handler.java类的sendMessageDelayed方法
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
5.调用Handler.java类的sendMessageAtTime方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
//这里如果queue为空也会报错,也就是没有创建的looper实例
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
伙伴们发现return中的方法多了一个queue,他是从哪儿来的呢?
看到MessageQueue queue = mQueue;嗯?mQueue又从哪儿来的呢?再看
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
可以看出mQueue = looper.mQueue原来是Looper类的实例looper调用了Looper类的成员变量mQueue
初始化的,looper实例有哪儿来的?这个时候Looper.prepare();出来了
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));
}
看looper实例是sThreadLocal.set(new Looper(quitAllowed));这么出来的,原来一开始在初始化Hanler之前就
通过Looper.prepare()实例化并放到了sThreadLocal中了,而在Looper的构造方法中实例化了mQueue,这个时候
mQueue = loopery.mQueue中looper实例和mQueue成员变量都有了吧(先不要管sThreadLocal是啥,就当他是一个Looper
的容器,由上可以看出每个线程对应一个looper实例,每个looper实例对应一个它自己的MessageQueue)
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
再看Looper.java类中myQueue方法显示通过myLooper().mQueue实现
public static MessageQueue myQueue() {
return myLooper().mQueue;
}
而myLooper().mQueue刚好就是sThreadLocal.get().mQueue也就是通过Looper.prepare()实例化的looper实例对应的MessageQueue
public static Looper myLooper() {
return sThreadLocal.get();
}
回到sendMessageAtTime方法继续往下看
6.调用MessageQueue.java类的enqueueMessage方法
boolean enqueueMessage(Message msg, long when) {
//判断目标handler是否存在
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
这里实现了消息队列的排队与队序管理,哎,伙伴们肯定疑惑,这也没有实现传递数据啊,为啥handleMessage(Message msg) {}
就能接收到数据了呢?好吧别急,我们还没看Looper.loop()呢。
7.调用Looper.java中的loop()方法
从代码中可以看出他依然获取了之前Looper.prepare()中的looper实例和对应的MessageQueue,当然数据信息也在里面,在看到
msg.target.dispatchMessage(msg);中msg.target当然就是目标的Handler了也就是发送数据消息的mHandler,接下来我们看看dispatchMessage(msg)
public static void loop() {
//获取到Looper.prepare()中的looper实例
final Looper me = myLooper();
//如果为空就会报No Looper; Looper.prepare() wasn't called on this thread.的错
//一开始叫伙伴们试试不写Looper.prepare()会报啥错,看看是不是这个,哈哈
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();
}
}
8.调用Handler.java中的dispatchMessage()方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Ok,看到了吧,这里调用了Handler.java中的handleMessage(msg)方法,并把数据信息msg传递了过来,当然在UI线程中就可以
通过当前Handler实例对象mHandler重写handleMessage(msg)方法获取数据信息更新UI咯。
ps:该篇文章是本人对Handler+Thread的学习理解,若有不对的地方,希望能指出来,共同进步。
推荐文章: http://blog.youkuaiyun.com/guolin_blog/article/details/9991569