前阵子,我在知乎上看到这样一个回答,说的是三年Android开发小哥去面试,情景对话如下;
-
面试官:你工作三年,应该看过源码了吧。看的懂吗?
-
小哥一脸尴尬的看着面试官说道:没怎么接触过,这几年都是在CURD。
-
面试官:你之前是在哪个公司呢?
-
小哥:XXX信息技术有限公司
-
面试官:上家公司是做什么的呢?
-
小哥:帮大公司的一些项目写业务的
-
面试官:不好意思,你不适合我们招聘我们岗位的要求。
结束面试后,小哥一脸愁容的走出了会议室。
为什么会出现这种情况呢?
其实大家都明白,有着小哥相同遭遇的人不少。工作三年的程序员,对源码竟然很陌生,这时候肯定有人要说了:公司不要求我们看懂源码?但是你要想想这家公司不要求,但是你离职以后、下一家公司你敢保证不要吗?就算你一直在一家公司干下去,你想一辈子就只在底层当码农吗?
为了让大家在短时间内更容易阅读并分析源码,我花了几个小时写了这篇博客,请大家务必看下去
阅读源码能解决什么问题?
很多时候为了解决一个问题必须先理解Android系统的运行原理,这时候就得阅读应用层框架的源码。
学会阅读系统源码或者他人的代码,这是研发必备的技能之一,只有了解别人写的东西才能在他之上更好的行事,同时也能去学习和借鉴他人优秀的代码思想。
那么该如何阅读并分析Android源码呢?
这里我只讲一些很快就可以上手的源码,不需要下载和编译系统源码。
我们下载Android SDK的时候一般都会下载相应版本的源码(sdk/sources目录下),在AS(Android Studio)上追踪系统代码时会自动打开源码文件,如果没有源码则会在右上角提示下载:
系统的源码一般多且复杂,虽然有不少注释,但如果纯靠阅读去理解会相当吃力,很难把握整体流程。我们需要结合实际使用场景,通过debug去分析代码的运行逻辑。那么SDK的版本有那么多,应该查看哪个版本的源码呢?
这个根据需要,如果要查看最新7.0的源码就查看相应的。如果没有指定的版本,一般你打开的SDK自带的虚拟机的版本是多少就查看相应版本的代码。
我们可以通过在项目build.gradle文件里面配置compileSdkVersion为指定的版本,这样在AS上追踪代码时跳转的即是对应版本的源码文件。
(这里我强调的是自带的虚拟机,而不是真机或其他第三方的虚拟机。因为自带的虚拟机的rom可以保证代码是没有修改过的,跟官方源码的行数可以对得上。)
例如,一般情况下,我使用版本22的虚拟机:
接着把项目的compileSdkVersion配置为22:
android { compileSdkVersion 22 buildToolsVersion "22.0.0" ... }
然后在AS上追踪系统代码,或者通过双击shift键,输入需要查找的系统类:
我们可以看到这时候的源码版本都是android-22。
接下来我们就要根据使用场景,寻找一个入口的地方,打一个断点,同时在其他觉得可疑的关键地方也打入断点,进入debug模式,这样逻辑就会在断点的地方停止,这时候就可以查看代码的运行逻辑,借助AS强大的debug功能分析代码。
debug一定要有耐心,而且要多尝试设置可疑断点,让代码在关键地方停止。多运用几次就可以快速阅读和分析系统源码,明白其中的代码逻辑。
这里给个建议,一开始只需要把握某一个功能的整体代码逻辑,设置几个关键断点,通过断点阅读代码,不要深入细节无法自拔。等理解了整体逻辑之后,再考虑从细节地方入手,一句句代码debug下去。
最后,我们通过一个实际场景运用上面的方法去分析"View的OnClickListener.onClick()方法是怎样被触发的"。
首先新建一个项目,build.gradle里的配置如下:
android { compileSdkVersion 22 ... }
创建一个页面,里面存在一个按钮,设置了OnClickListener,启动自带的api版本为22的虚拟机,运行项目,效果如下:
那么接下来debug从哪里入手呢?我们并不知道OnClickListener在哪里被回调,因此并不能预先在系统代码里打断点。
这里我们可以观察调用view.setOnClickListener()的代码,然后查看OnClickListener对象保存在哪,什么时候调用,然后在关键地方打入断点。
但其实还有更简单的方法,我们采用逆向思维,直接在OnClikcListener.onClick()方法里面打入断点:
进入debug模式:
点击按钮,然后代码会执行到断点的地方,这个时候我们查看左下角调用栈:
可以看到onClick方法是被View.performClick()方法调用,继续下查看调用栈发现performClick方法又是在PerformClick对象中执行:
PerformClick对象实现了Runnable,run()方法是在主线程消息队列执行的,所以接下来我们需要在View的源码里追踪代码,借助AS强大的功能查看PerformClick对象哪里被创建和被调用:
从上面可以看出关键地方,PerformClick在View.onTouchEvent()方法被调用。想必接下来要分析"View的OnClickListener.onClick()方法是怎样被触发的"这个问题就知道如何下手了,比如我们可以在View.onTouchEvent()打入断点,一步步代码查看具体的代码逻辑:
整个的过程大概就这样,当然不同问题要灵活处理,重要的是多实践多操作,就会得出一套自己解决问题的方法。
网络上分析源码的学习资料很多,但是大部分都是零零散散,不太完整。分享给大家一份我整理的源码快速进阶笔记(包括了各类开发APP的源码资料和源码学习笔记)
各类开发APP的源码资料
源码及设计模式学习资料
有需要的朋友(点击即可免费领取)
商城类—仿每日优鲜APP应用源码(部分源码)
仿大众点评应用源码(部分截图)
最后
有需要的朋友赶紧点赞起来哦,(点击即可免费领取)免费获取这两份笔记哦