Android Framework 如何学习,如何从应用深入到Framework?|牛气冲天新年征文

5,076 阅读8分钟

系列文章索引

并发系列:线程锁事

  1. 篇一:为什么CountDownlatch能保证执行顺序?

  2. 篇二:并发容器为什么能实现高效并发?

  3. 篇三:从ReentrientLock看锁的正确使用姿势

新系列:Android11系统源码解析

  1. Android11源码分析:Mac环境如何下载Android源码?

  2. Android11源码分析:应用是如何启动的?

  3. Android11源码分析:Activity是怎么启动的?

  4. Android11源码分析:Service启动流程分析

  5. Android11源码分析:静态广播是如何收到通知的?

  6. Android11源码分析:binder是如何实现跨进程的?(创作中)

  7. 番外篇 - 插件化探索:插件Activity是如何启动的?

  8. Android11源码分析: UI到底为什么会卡顿?

  9. Android11源码分析:SurfaceFlinger是如何对vsync信号进行分发的?(创作中)

经典系列:Android10系统启动流程

  1. 源码下载及编译

  2. Android系统启动流程纵览

  3. init进程源码解析

  4. zygote进程源码解析

  5. systemServer源码解析

前言

作为一个基本上可以说是从0开始起步读源码,到现在已经完成了一系列源码剖析技术文章的作者来讲,我觉得我的经验还是有一定的可借鉴性的

如何深入学习Framework源码?

首先,我也是一个应用层开发者,我想大部分有“如何深入framework源码”这个疑问的,应该大都是应用层开发

那对于我们来讲,读源码最大的问题,其实是没有应用场景,或者说短期来看成本高,收益底,容易半途而废

针对这个问题,首先是要要有一定的定力和研究精神,打算拿下哪部分的源码分析,即使遇到再多的问题,也要想办法解决,自己定的目标,跪着也要完成 其次,就是从什么方向入手,正如题主所说,源码很多,ndroid11的aosp整个下载下来,有150G左右,所以找入手点很重要,否则只会把源码下载完成之后就让它在硬盘里吃灰了

(上图为Android11的aosp源码大小)

针对应用层开发来讲,我这里提供几个面试比较常问,也比较容易上手的入手点

  1. 四大组件启动流程
  2. 应用启动流程
  3. 系统启动流程
  4. 音频相关内容

这里看上去的4个小点,其实真正做起来至少要半年的时间,因为里面涉及的内容既多又深,就第一点来讲,Activity启动流程就够你搞至少两周了,这里面会涉及ActivityThread ,AMS ,Zygote, Binder跨进程调用等一系列知识

这里再额外提一句,看到weishu大佬回答说不要关注各种流程的跟踪,其实我是不认同的,当然这只是小弟我基于自身知识和认知的看法

对于广大的应用层开发者也是一样,我们要明白自身的定位,小白走小白的路,大佬走大佬的路,个人认为,不论是跟各种系统流程的调用链也好,还是按系统服务去整块梳理也好,这些都是“过程”,而我们的目标,是深入framework源码,试问连调用链都没跟过,怎么深入源码?

当然,我也同意weishu大佬说的,要分析其后面涉及的思想和原理,但是这是第二层了,没有第一层的基础就想干第二层的事情,无异于空中楼阁,痴人说梦

回到正题上来,我们已经搞定了从什么地方入手,第二个要解决的问题是,我们需要具备什么样的基础,才能读懂源码,或者有能力去读源码

个人认为,当你提出如何深入学习Framework源码这个问题的时候,你就已经具备了最基础的条件--探索欲和求知欲。当然这个东西比较虚,我再讲一些实在的

目前新版本的AOSP底层代码基本上都用C++重构过了,因此如果你想深入到native层,比如我们最常提到的handler,其实在native层也有一套实现,取消息的时候会通过管道机制进行唤醒通知,避免死等阻塞问题 那是不是说我们必须要先有C++或C语言基础才能去读源码呢?我认为,有基础自然好,没有也不会有太大影响,边度边补相关知识,可能比学完C++再来继续读源码效率要更高

因此,在我看来,不论你基础如何,只要有应用层开发经验,有探索和研究Framework的兴趣和欲望,这就够了。只要开始,就是进步

第三点我要讲的是,深入到什么程度是合适的。我在读源码的过程中,经常会跟着单个调用链越挖越深,比如在研究系统启动流程的时候,甚至到了虚拟机层面和汇编层面,但是一般来讲,我们不需要挖这么深,一来是没有必要,二来确实会花费大量精力,且很难见到成效

因此我在研究某个点的时候,会把这个点拆分成一个个的小问题,举一个具体的例子,在研究SystemServer相关流程的时候,我给自己提了这些问题

  1. SystemServer是如何被fork出来的
  2. SystemServer做了些什么事情
  3. SystemServiceManager是负责什么的?
  4. SystemServiceManager是如何创建的?
  5. ServiceManager是负责什么的?
  6. 启动服务有几种方式?他们之间有什么区别?
  7. SystemServiceManager和ServiceManager有什么区别?
  8. LocalService是负责什么工作的?
  9. SystemServer是服务端进程,那么谁是客户端进程?他们是如何通信的?内部机制是什么?(Binder相关的问题)

当然一上来可能提不出问题,或者不知道里面都涉及哪些重要的类,我们可以先阅读相关文章,有个大概的思路,此时就能提出一些基础的问题了,然后在阅读源码的过程中再不断提问和归纳,这也是我写源码分析文章的步骤和思路

第四点,我要提到的就是,要有正向反馈。很多人不是没有定力,但就是感觉读不下去,很大的原因就是没有正向反馈。我的正向反馈来自于我的文章产出,文章阅读量和博客关注度,以及和小伙伴们可以互相交流(但大多数时候,越深入的方向,可交流的人越有限)

我也建议大家在学习framework的时候可以多多交流,产出文章和成果,激励自己继续在这条路上走下去

第五点,需要提醒大家的是

如果你工作中有涉及相关内容(比如插件化,音视频,launcher,setting,AudioManger等),请优先研究相关源码

如果没有涉及,你可以参考我上面提到的入手点进行研究,只有你拥有了阅读和研究的能力,才能更好的完成更有挑战性的,甚至跨入Framework开发的行列当中

最后,在谈一谈阅读源码的好处吧,当你研究完一两个模块之后再来看,可能体会更深

正如weishu大神所讲,研究framework的好处并不在于记住了哪些调用流程,这些不是目的(但是确实必不可少的过程哦!),我们的目的是从更深的,或者说从更整体的视角来看我们的技术 比如四大组件是我们开发中最常用的,但fragment也是我们开发中常用的,为什么它不能称得上是“第五大组件”呢?

当我研究完四大组件的源码之后,我发现了四大组件最大的特点--支持跨进程,他们的启动流程都会涉及我的进程是否启动了,是否需要先跟zygote通信去fork出进程,然后再执行组件自身的启动逻辑 因此四大组件的重量级是很重的,而frament只是依赖于activity的的一部分,远达不到如此的重量级,因此也就自然不能成为“第五大组件”了

再说回来,阅读源码的好处

  1. 就是在于对应用层开发能理解的更深刻;
  2. 当遇到一些疑难问题的时候,我们有能力通过读源码去深挖问题的原因,并最终解决问题;
  3. 在于整体的阅读源码能力的提升,当我们在看其他三方库源码的时候,就会更得心应手了,连AOSP这个近200G的庞然大物都能搞定,Okhttp在它面前简直就是弟弟

最后

最后的最后,如果你打算开始读源码了,可以先看一些相关的文章,比如笔者的文章(狗头)

我是释然小师弟,如果本文对你有所启发,请点赞支持下!我们下篇文章再见啦!