「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。
一般线程消息传递过程
主线程Looper的来源
之前已经说过了主线程的消息处理过程,但是之前还有一个问题,就是主线程的Looper是怎么来的?我们之前在ContentProvider的介绍中说过,程序的主线程是ActivityThread,app的入口是其main方法,在这个方法中会重新持有一个ActivityThread的对象。
显然,答案需要我们到ActivityThread的main方法中去寻找
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();
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");
}
源代码比较长,这里只截取部分代码,可以发现这里有一个prepareMainLooper()和loop()方法,这两个方法也就是我们之前介绍的Looper的两个主要方法(一般线程是prepare()方法),其中prepareMainLooper()方法如下
@Deprecated
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
其本质还是用prepare方法在主线程的ThreadLocalMap中添加Looper。
一般线程的消息机制
从主线程的消息机制来看,一个线程如果要使用android的消息机制那么必须具备几个条件,Looper,ThreadLocal,MessageQueue,Handler,其中ThreadLocal是线程创建的时候就有的,MessageQueue是Looper创建的时候创建的,因此,也就只剩下Looper和Handler需要我们自己手动添加(Main线程甚至只需要添加Handler就好)。 所以过程如下:
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
Log.d("message",(String)msg.obj);
return false;
}
});
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.obj = "abc";
handler.sendMessage(message);
}
}).start();
Looper.loop();
}
}).start();
首先需要prepare()方法为当前线程添加Looper,接着添加一个事件处理的Handler,最终在线程结尾处不断从消息队列中取得Message进行处理。
总结
至此,整个android的消息传递机制稍微简单地介绍了一遍,总的来说需要记住这么几个类或者对象,ThreadLocal,ThreadLocal.ThreadLocalMap,Looper,MessageQueue,Handler,Thread,ActivityThread,AcitivityThread的main方法,记住这几个点后,然后梳理它们的关系,这样就可以将点连成线,梳理出整个脉络