在程序的入口
public static void main(String[] args) {
...
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
// 可以看成一个线程
ActivityThread thread = new ActivityThread();
// ams 和 当前进程 进行一个绑定
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
程序启动,到结束,main方法就结束了,但是app结束,就退出程序了,所以不能结束,Looper.loop(); 可以看成一个死循环
如果要结束程序,要loop结束,handler接收到消息,就会结束
case EXIT_APPLICATION:
if (mInitialApplication != null) {
mInitialApplication.onTerminate();
}
Looper.myLooper().quit(); // 退出loop
系统Handler
客户端Handler
final H mH = new H(); // 饿汉式加载,直接初始化
handleMessage 方法中接收系统的消息,4大组件生命周期,都是通过发消息Handler来处理
我们来看Looper.loop();
public static void loop() {
// 获取 消息泵
final Looper me = myLooper();
// 消息泵中有一个消息队列
final MessageQueue queue = me.mQueue;
...
// 进行死循环
for (;;) {
Message msg = queue.next(); // 注释1
// 如果没有消息,则继续循环
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
// 获取到消息,并进行派发target 就是handler 注释2
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
// 进行消息的回收处理
msg.recycleUnchecked();
}
}
我们看looper 就一只在循环,当在队列中没有消息继续循环,有了消息,看到注释1 处,进行获取消息,注释2处,进行派发消息
获取消息,并不是队列的先进先出,因为消息带有时间,根据时间判断,如果当前时间小于消息时间,就先不发送,大于当前时间,则按队列顺序发送
# 进行获取消息,是在MessageQueue.java
@UnsupportedAppUsage
Message next() {
...
// 也是个死循环,因为消息有时间,没到就等到时间
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
...
if (msg != null) {
// 当前时间 和 消息时间比较
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
...
}
}
进行派发消息
# 注释2处,进行派发消息
# Handler
public void dispatchMessage(@NonNull Message msg) {
// callback 其实就一个 Runnable
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 当没有Runnable 则调用自己重写的handleMessage方法,里面是空的
handleMessage(msg);
}
}
// 相当于调用了 Runnable 的run方法,其实还是在当前线程执行
private static void handleCallback(Message message) {
message.callback.run();
}
# Message
Runnable callback;
上述写法 ,相当于派发了消息,如果有Callback,就执行run,没有就执行 handleMessage
Handler handler = new Handler();
int i = 0;
Runnable run = new Runnable() {
@Override
public void run() {
Log.e(TAG, "run: " + i++);
handler.postDelayed(run, 1000);
if(i == 10){
handler.removeCallbacks(run);
}
}
};
handler.post(run);
handler的发送消息,是可以带时间的,分为马上发,或者延迟发,发送消息的时候,消息是从消息吃中取,当前开始也没有,也是new出来的,当handler执行完消息派发,则在loop方法中调用msg.recycleUnchecked();来进行回收
# message
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();
}
# handler
//uptimeMillis 就是这条消息的时间
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
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);
}
消息 一种有Runnable 一种是没有
因为是多线程的,每个线程都会访问同一个message,所以会出现问题,就出现了ThreadLocal,里面放的就是Looper
handler 可以这样理解,
要使用handler,就需要进行Looper.prepare();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.prepareMainLooper();之后又有Looper.loop();
handler在系统中存在2中通信,1系统的,Activity的生命周期,2自己写的,为什么自己写的不可以像系统handler发消息呢?
因为handler 是通过ThreadLocal这个类进行封装,里面包含了<Loop>,loop中又有Thread当前线程,MessageQueue消息队列,handler通过发送消息发送到当前线程的MessageQueue中,又从中取消息,这样就不会发送到系统里面了
handler 容易造成内存泄露,我们可以在handler post的时候弄个Runnable,之后再Activity结束时候,进行handler.removeCallbacks(run);// 移除创建的Runnable
网友评论