那么,App 主线程是怎么回事?下面是 App 进程创建后,ActivityThread.main 方法被调用的逻辑
frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
…
// 创建 Looper、Handler、MessageQueue
Looper.prepareMainLooper();
…
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
// 指定主线程的 handler 为 H
sMainThreadHandler = thread.getHandler();
}
…
// 开始准备接收消息
Looper.loop();
}
}
// 准备主线程的 Looper
frameworks/base/core/java/android/os/Looper.java
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 方法中会创建一个 Looper 对象
frameworks/base/core/java/android/os/Looper.java
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 对象创建的时候,同时创建一个 MessageQueue
frameworks/base/core/java/android/os/Looper.java
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
通过上面的流程,主线程的 Looper、MessageQueue 都已经创建好了,这就打下了 Message 机制的基础,后续有 Message 进来,就会进入主线程的 MessageQueue ,然后 Looper 会把他派发给对应的 Handler
对于主线程来说,这个 Handler 就在 ActivityThread 里面,下面截取一小段 Handler 的方法,大家可以看一下,熟悉代码的应该知道,BIND_APPLICATION 就是大家经常在 Systrace 中看到的新进程启动时候的那一段
frameworks/base/core/java/android/app/ActivityThread.java
class H extends Handler {
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “bindApplication”);
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
所以之前也有人会问,ActivityThread 是主线程么?为什么没有继承 Thread ?看了上面的流程,答案就很清楚了,ActivityThread 并不是一个 Thread ,只不过他有个叫 H 的 Handler 来处理主线程的 Message 而已;另外 Activity、Service、BroadcastReceiver 组件的生命周期都是在主线程执行的,通过上面的讲解应该就比较好理解了:都是在 ActivityThread 的 H 这个 Handler 里面处理的.
线程间通信
App 主线程初始化完成后,Message 机制跑起来了,那么子线程呢?其实也是一样的,子线程也有一套 Message 机制,有它自己的 MessageQueue、Looper、Handler。
那么线程间的 Message 通信就好理解了,Looper 在派发 Message 的时候,会根据 Message 自己的意愿(target,即目标 Handler),派发给对应的 Handler 去处理,这里的 Handler 既可以是子线程的 Handler ,也是主线程的 Handler,也可以是 App 进程里面其他的 Handler,只要知道且指定这个 Handler 即可
比如非常典型的一个例子就是 AsyncTask,如果你在主线程创建了 AsyncTask ,那么在 AsyncTask 执行在子线程完耗时任务后,就会给主线程的 Handler 发 Message,来更新主线程的 UI
子线程能不能更新 UI
既然主线程和子线程都是 Message 机制,子线程到底能不能更新 UI 呢?答案是可以的,但是会出问题,比如主线程正在执行 doFrame ,Measure 方法刚刚走完,你子线程把 View 的宽高给改掉了,那么主线程后续执行 Layout 的时候,View 的位置摆放就可能会出问题(当然我没有试过,感兴趣的小伙伴可以把 checkThread 限制代码去掉,然后在子线程更新 UI 试试)
所以 Android 为了避免这种情况,在有 UI 更新的地方,都加了 checkThread() ,来确保只有主线程才能更新 UI
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
“Only the original thread that created a view hierarchy can touch its views.”);
}
}
最后
关于如何学习Android Framework开发知识,最近有幸在前阿里技术总监手里扒到这份Android framework高级开发笔记,今天就拿出来分享给大家。
本笔记讲解了Framework的主要模块,从环境的部署到技术的应用,再到项目实战,让我们不仅是学习框架技术的使用,而且可以学习到使用架构如何解决实际的问题,由浅入深,详细解析Framework,让你简单高效学完这块知识!
如有需要获取完整的资料文档的朋友可以【点击我】免费获取。
第一章:深入解析Binder
Binder机制作为进程间通信的一种手段,基本上贯穿了andorid框架层的全部。所以首先必须要搞懂的Android Binder的基本通信机制。Binder机制作为进程间通信的一种手段,基本上贯穿了andorid框架层的全部。所以首先必须要搞懂的Android Binder的基本通信机制。
本章知识点
- Binder 系列—开篇
- Binder Driver 初探
- Binder Driver 再探
- Binder 启动 ServiceManager
- 获取 ServiceManager
- 注册服务(addService)
- 获取服务(getService)
- Framework 层分析
- 如何使用 Binder
- 如何使用 AIDL
- Binder 总结
- Binder 面试题全解析
第二章:深入解析Handler
本章先宏观理论分析与 Message 源码分析,再到MessageQueue 的源码分析,Looper 的源码分析,handler 的源码分析,Handler 机制实现原理总结。最后还整理Handler 所有面试题大全解析。
Handler这章内容很长,但思路是循序渐进的,如果你能坚持读完我相信肯定不会让你失望。
本章知识点
- 宏观理论分析与Message源码分析
- MessageQueue的源码分析
- Looper的源码分析
- handler的源码分析
- Handler机制实现原理总结
- Handler面试题全解析
第三章:Dalvik VM 进程系统
Andorid系统启动、init 进程、Zygote、SystemServer启动流程、 应用程序的创建使用,Activity的创建、销毁 Handler和Looper。
结尾
最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
高级UI,自定义View
UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。
不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!
[外链图片转存中…(img-WBU06YSb-1715345838966)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!