阅读源码的半程总结-读源码都读什么

讲完了为什么要读源码,然后再说读源码都读什么。我应该不会写怎么读的问题了,毕竟看代码跟写代码不一样,属于一个很玄学的东西,每个人都有自己的一套思路。

那么读源码都读什么?说到底也就是读源码能学到什么?从我自己的角度,大概能分为几个角度:学习优秀的解决方案;学习优秀的代码风格;学习设计模式的使用场景;学习搭架构的思路;学习一些平时没见过和想不到的黑科技。

学习优秀的解决方案

这个算是读源码比较功利也比较实际的用途。同一个需求永远都会有不同的解决方案,这时候就可以通过看类似框架的源码来搞清楚最成熟的解决方案是什么。一个简单的例子,在我们现有的项目中图片选择器采用了获取图片和视频绝对路径的方案,最终为了显示视频缩略图,我还必须定制一下Glide。但是知乎最近开源的Matisse,获取的就是图片和文件content:// 格式的URL,Glide在解析这种路径有对应的MediaStoreStreamLoader,完美解决了展示视频缩略图的问题。虽然同样解决了问题,但是Matisse解决的似乎就更加优雅。

学习优秀的代码风格

只学代码风格,我个人觉得最好读一些通用的、底层的东西。比如Java的代码风格,那就去读JDK一些常用类,Js的代码风格,我个人可能就会看看经典的jQuery或者vue.js。没有什么三方库的代码会比它们的代码更简洁,使用更准确。

学习设计模式

写代码过了初级阶段,多多少少都会开始用到设计模式,无论是刻意还是无意。可是设计模式那么多种,书里教了这是怎么回事,到了真正设计架构的时候,却不知道该用哪种了。简单的单例模式、建造者模式、工厂方法模式就不说了,基本都是固定的套路和使用场景。但是到了稍微复杂点的,我是确实不清楚该不该用,该用哪种,该怎么用。用少了,代码不解耦,扩展性差,不好维护。用多了,变成了“面向设计模式编程”,代码量成倍扩张,却没做多少事。这时候就有优质的源码给我们铺路了。

在被动读了OkHttp之后,我后来又主动重读了一遍。大家都知道Interceptor是OkHttp一个很强大的接口,利用这个接口几乎可以在一个完整的请求中做任何事情。但是其实在OkHttp内部也是用Interceptor做了重定向、连接服务器、发送和接收请求以及缓存这些事情,连在一起,就是一个责任链模式。

在项目里我没有用过Picasso,但是因为它和Glide使用方法的相似性,我花时间看了它的源码。然后我才发现Picasso和Glide完全走了两个极端,Picasso算是大道至简,只有一个包,能不做的事情都不做,所有目的都只为图片的加载。而Glide则开放了所有的接口,所有步骤都可以定制,甚至可以像我那样为具体需求增加自己的feature。但是为什么我们会觉得他们用起来差不多呢?说到底他们都用了外观模式,我们在调用的时候只知道拿起Glide和Picasso开始用,其他的工作都交给内部去做了。

而我读过的源码中设计模式的集大成者,应该是Retrofit了。这个库的源码不多不少,但是加上配套的一堆Adapter和Convertor,外观模式、代理模式、策略模式、适配器模式、装饰模式都用到了,甚至同一个接口不同的实现都可以用到不同的设计模式。完全解耦,所有步骤与Glide一样都可以定制。

对于设计模式的学习,我个人的感受还是应该多看多写才能真正掌握并最终能够游刃有余,而优秀的源码可是说是提供了最完美的解决方案。

学习搭架构的思路

从做Android开发来说,每个项目最常用的就是网路库和图片库了。如果能从零设计这两个库,那么其他的架构都是大同小异了。

以网络库Volley为例,读完源码,基本能形成:

1

Request --> Dispatcher --> Cache --> HttpStack

这一套思路。其实再看其他的网路库都大同小异。我们自己实现,根据这个思路基本就足够了。

再以Glide为例,整个架构基本是由RequestManager、Engine、Cache、Target这几部分组成,其他的也是差不多的思路。

优质的库都是在大量试错和妥协后的结果,基本是用最合理的方式实现最终的需求,在设计类似的框架时,先借鉴,再改进,设计其他的架构差不多也是这么一套方法。

学习一些黑科技

这个就属于堆经验了。同样类型的库架构上大同小异,但是每个库又有它的独到之处,只有真正把源码读完,才能学习到有意思的地方。这部分只举例子,不具体分析:

  • Glide利用一个空Fragment的生命周期实现每个请求与所属上下文生命周期的绑定

  • RecyclerView不再像ListView那样缓存View,二是直接缓存ViewHolder,这是许多仿写ListView的人从没想到过的思路

  • Retrofit使用动态代理拿到注解的请求详情

  • OkHttp的责任链模式 虽然是个设计模式,但是这个思路太巧妙了

  • Picasso的磁盘缓存本质上是OkHttp的磁盘缓存!当时看到这部分源码是特别惊艳的,同时我也感受到了Square的工程师们对他们的全家桶的无比自信

这些有意思的设计细节我们不一定能用得到,但是能为我们解决平时的问题提供更多的思路,同时也能学到更多不常用的知识。

总结

除了这些提到的库,其他一些源码我也多少度过,只能说代码神奇就在这里,每个人的代码风格、设计思路都不一样,但是最终都能产出一个优质的开源框架,很多苦看起来架构差不多,但是内部实现又是千奇百怪,同一种模块似乎每种设计模式都能派上用场。读源码,抛去为了解决问题、为了提升技能的这些功利性的想法,只是体会这些强人的思路,已经是一种享受了吧。