1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android-handler looper messageQueue message

android-handler looper messageQueue message

时间:2018-04-11 06:08:18

相关推荐

android-handler looper messageQueue message

Handler创建,必须有个一个Looper,主线程自己创建了。其他线程需要自己创建,默认是没有的。创建方法

1. 这种方法是先创建一个系统定义好的HandlerThread,这个是跑在非UI线程中的,已经创建好了looper,直接用就可以了.创建handler有多个构造函数,具体看源码

HandlerThread threadhandler = new HandlerThread("1111");

threadhandler.start();

myhandler = new myHandler(threadhandler.getLooper());

2. 自己创建一个新的线程,在线程中调用Looper.prepare();然后写处理message回调方法,接着还要调用looper.loop();

class LooperThread extends Thread {

public Handler mHandler;

public void run() {

Looper.prepare();

mHandler = new Handler() {

public void handleMessage(Message msg) {

// process incoming messages here

}

};

Looper.loop();

}

}

为什么一定要有一个Looper呢?

因为handler的无参数构造函数里需要looper,如果为空就抛异常。

如何设置looper?

调用Looper.prepare();这里会判断当前的线程是不是已经有looper了,有的话会抛异常,这就是说一个线程只能有一个looper。

Message是什么,有什么用?

存放消息的用的,它有很多属性。特别说明target,表示的就是处理它的handler,next属性,这就是利用了链表结构来构造的消息队列,message.next表示着当前消息的下一个,是按照时间来的,只能顺序不能反过来,他没有prev属性。

这里需要说一下他的Spool静态属性,这是一个消息池,Spool自己就是一个Message对象,刚开始的时候他是null的,什么时候它有东西的呢?

void recycleUnchecked() {

// Mark the message as in use while it remains in the recycled object pool.

// Clear out all other details.

flags = FLAG_IN_USE;

what = 0;

arg1 = 0;

arg2 = 0;

obj = null;

replyTo = null;

sendingUid = -1;

when = 0;

target = null;

callback = null;

data = null;

synchronized (sPoolSync) {

if (sPoolSize < MAX_POOL_SIZE) {

next = sPool;

sPool = this;

sPoolSize++;

}

}

}

看这个方法,这个方法是looper中循环处理完一个message之后做的事情,它回收了这个message,并且将这个被回收的message和已有的Spool链接起来,再将Spool指向这个回收的message,利用这种方法将回收的message都给串了起来。

message -> spool -> null

spool(被回收的message)-> message(旧的spool) -> null

消息池怎么被使用的?

public static Message obtain() {

synchronized (sPoolSync) {

if (sPool != null) {

Message m = sPool;

sPool = m.next;

m.next = null;

m.flags = 0; // clear in-use flag

sPoolSize--;

return m;

}

}

return new Message();

}

利用obtain的方法得到一个消息池中的第一个空message,并且spool指向第二个元素,剩余的空消息数-1;

MessageQueue是什么,有什么用?

用来操作messages,例如handler发送消息过来,他需要把消息按照顺序串起来。还有处理完消息后他需要把消息从消息队列中删除等等。

handler有什么用?

发送和处理消息。handler通过sendmessage等方法发送消息,最终都是通过sendMessageAtTime(这里最终是调用了enqueueMessage方法,其中uptimeMillis参数是SystemClock.uptimeMillis() + delayMillis,所以想要优先处理runable,就是要让时间戳在所有message之前,利用

sendMessageAtFrontOfQueue方法,这个参数会传递0,这样就会优先处理了)来处理发送给MessageQueue。然后通过looper回调函数msg.target.dispatchMessage(msg)-->handler的handleMessage()方法具体处理。

handler还可以使用post方法将runnable传给消息队列message有callback属性,在looper的dispatchMessage()方法中,如果是runnable就直接run()了;

最后有个疑问:到底是什么样的机制可以让looper循环去处理message?

while(true){

Messagemsg=queue.next();//mightblock

if(msg!=null){

if(msg.target==null){

return;

}

if(me.mLogging!=null)me.mLogging.println( ">>>>>Dispatchingto"+msg.target+""

+msg.callback+":"+msg.what );

msg.target.dispatchMessage(msg);

if(me.mLogging!=null)me.mLogging.println( "<<<<<Finishedto"+msg.target+""

+msg.callback);

msg.recycle();

}

看到Messagemsg=queue.next();//mightblock 这句话,获得待处理的message,这里可能会堵塞,没有message的时候就循环等待,直到messageQueue退出

现在再看看queue.next方法

if (msg != null && msg.target == null) {

// Stalled by a barrier. Find the next asynchronous message in the queue.

do {

prevMsg = msg;

msg = msg.next;

} while (msg != null && !msg.isAsynchronous());

}

这部分代码进入条件是target是null,那么什么时候target会是null呢,首先我们要明确,我们只有2种方法往messageQueue的mMessages里插入message---enqueueMessage(sendMessage等最终都是走的它)和enqueueBarrier。我们用handler在setMessage的时候enqueueMessage方法已经

msg.target = this;

而且如果我们使用的是带参数的Message中的obtain方法也会设置target。

那么无疑就是enqueueBarrier方法,这个方法只有一个入口,就是Looper的postSyncBarrier(),它会返回一个int值,用于之后的removeSyncBarrier(int)。

int enqueueSyncBarrier(long when) {

// Enqueue a new sync barrier token.

// We don't need to wake the queue because the purpose of a barrier is to stall it.

synchronized (this) {

final int token = mNextBarrierToken++;

final Message msg = Message.obtain();//这里返回一个target为null的Message

msg.markInUse();

msg.when = when;

msg.arg1 = token;

.....

}

}

然后接着看queue.next,如果是阻断msg,那么就一直找到msg是isAsynchronous的,然后接着处理,这个isAsynchronous有2种设置方法,一个是handler构造参数里面传的,那么所有的sendMessage都会打上异步标签。还有一种就是单独调用一个message的setAsynchronous。

这样的话,当阻断的时候就会跳过普通的message,找到异步message去执行。

接着往下看next();

// Got a message.

mBlocked = false;

if (prevMsg != null) {

prevMsg.next = msg.next;//如果阻断的话,这里prevMsg就不是空,那么就会直接把标签是异步的message的上一个message的next直接指向标签是异步的message的下一个message,其实就是把异步message从消息队列中给抽出去了

} else {

mMessages = msg.next;//这里就是普通message的处理步骤,消息队列少了第一个元素

}

msg.next = null;

if (false) Log.v("MessageQueue", "Returning message: " + msg);

return msg;

到这里,阻断message还是在消息队列中,下次循环还是依照这个顺序执行。除非我们手动调用removeSyncBarrier方法才能正常处理普通的message。

这里得到个结论,mMessages的第一个元素不一定就是本次待处理的message。

这个阻断在源码中有地方使用:scheduleTraversals这个方法,这个方法是view的measure,layout,draw三部曲的入口。

void scheduleTraversals() {

if (!mTraversalScheduled) {

mTraversalScheduled = true;

mTraversalBarrier = mHandler.getLooper().postSyncBarrier();//这里,使用了阻断,此时只有message是异步的才可以被执行。

mChoreographer.postCallback(

Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);

if (!mUnbufferedInputDispatch) {

scheduleConsumeBatchedInput();

}

notifyRendererOfFramePending();

}

}

mTraversalRunnable这个Runnable执行的代码是

void doTraversal() {

if (mTraversalScheduled) {

mTraversalScheduled = false;

mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);//已经开始执行了,就把阻断remove掉,view展示完毕后继续正常处理普通的message

if (mProfile) {

....

}

}

}

优点快速展示,想了半天,为啥他不使用sendMessageAtFrontOfQueue这个方法优先执行mTraversalRunnable呢?可能原因,我们也可以主动调用改方法,那么岂不是就有可能我们的runnable优先与系统展示view了?使用阻断,他内部还是按照时间戳顺序执行的,就保证了view展示优先执行~!!!!!

接着看next();

// Run the idle handlers.

// We only ever reach this code block during the first iteration.

for (int i = 0; i < pendingIdleHandlerCount; i++) {

final IdleHandler idler = mPendingIdleHandlers[i];

mPendingIdleHandlers[i] = null; // release the reference to the handler

boolean keep = false;

try {

keep = idler.queueIdle();

} catch (Throwable t) {

Log.wtf("MessageQueue", "IdleHandler threw exception", t);

}

if (!keep) {

synchronized (this) {

mIdleHandlers.remove(idler);

}

}

}

这里还有代码,这是干嘛的?这这个就是执行idle handlers的,当之前的message,一个都找不到的时候,说明空闲,这个时候就可以执行IdleHandler了

使用方法就是调用MessageQueue的addIdleHandler方法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。