首先来说下为什么要读源码,有学习源码的必要吗?
为什么要阅读源码?
关于为什么阅读和学习源码,我个人认为可能有以下几点:
(一)吊打面试官,应对面试
为了找到更好的工作,应对面试,因为在面试中肯定会问到源码级别的问题,比如:为什么 HashMap 是线程不安全的?
如果你没有阅读过源码,面试官可能会对回答的结果不满意,进而导致面试结果不太理想,但如果你对源码有所研究,并能够很好地问答面试官的问题,这可能就是你的加分点,可以形成自己独特的竞争力,吊打面试官,升职加薪不是梦。
Android开发常见源码面试题
1.Glide :加载、缓存、LRU 算法 (如何自己设计一个大图加载框架) (LRUCache 原理)
2.EventBus
3.LeakCanary
4.ARouter
5.插件化(不同插件化机制原理与流派,优缺点。局限性)
6.热修复
7.RXJava (RxJava 的线程切换原理)
8.Retrofit (Retrofit 在 OkHttp 上做了哪些封装?动态代理和静态代理的区别,是怎么实现的)
9.OkHttp
...
(二)解决问题(bug)
IllegalArgumentException分析
java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:134)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:102)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:87)
at com.bumptech.glide.Glide.with(Glide.java:629)
at com.r...utils.glide.GlideHelper.loadImage(GlideHelper.java:229)
at com.r...DetailActivity.init(...DetailActivity.java:423)
...
...
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:887)
这个是在使用Glide的时候遇到的一个问题。这里如果单纯的找到日志中出现的我们写的类,并不能很好的找到解决思路。像这类问题呢,其实有个重要的方法那就是追本溯源,什么意思呢。别看着错误log日志一大堆,这段日志第一行大意是非法参数异常,不能为一个销毁的activity加载数据。第一行只是告诉我们错误大致意思,其实也知道了错误原因了。但是从第二行才可以找到问题的根源了。代码是:at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:134)。这段代码可以从Glide源码中找出。找到这个RequestManagerRetriever类的assertNotDestroyed()方法。源码如下:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static void assertNotDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
}
}
这里我们可以看出You cannot start a load for a destroyed activity这句话就是从这里向IllegalArgumentException()中作为参数传入,并且抛出了这个异常。在看这段代码,有个判断,一个是版本号大于J,并且activity.isDestroyed()都为真时,才抛出这个异常。版本号现在基本都是大于J了,而当我们activity销毁后,Glide还在工作,这时就抛出了这个异常了。相当于我主线程都销毁了,你Glide特么还工作个毛线?加载个数据谁要?因此程序不干了,给你报错吧。这里说明Glide写的真心不错的。这里抛出的这个异常信息还是非常明确的。下面来看看怎么处理:
if (Util.isOnMainThread()){
Glide.with(getApplicationContext()).load(url).into(view);
}
...
@Override
protected void onDestroy() {
super.onDestroy();
if (Util.isOnMainThread()){
Glide.with(this).pauseRequest();
}
}
在onDestory()中加入了判断,如果Activity销毁的话,那么Glide停止工作啦。老板都走了你加班给谁看呢???
从这个例子可以看出,log日志中除了我们自己写的类注意观察一下外,前两行日志还是非常重要的。
(三)提升编程能力
读一本好书,就是和许多高尚的人谈话。-歌德
和阅读一本好书一样,阅读源码就是和编程大牛面对面交流的机会,在许多优秀的开源项目中,它们的编码规范和架构设计都是很棒的,另外在设计上也使用了大量的设计模式,通过阅读和学习源码,能够快速提升我们的编码水平,以及对设计模式有更深的理解。
同时,在我们阅读完一个源码后,可以触类旁通,能够快速地对其他框架的源码进行阅读和学习,减少时间成本。
除了上述提到的原因之外,可能还有许多,在这里就不一一赘述了,那么在确定了要阅读源码之后,就让我们看下如何阅读源码吧!
如何阅读源码?
1.深入解析微信 MMKV 源码
[MMKV](https://gitee.com/vip204888/jav
a-p7) 是微信于 2018 年 9 月 20 日开源的一个 K-V 存储库,它与 SharedPreferences 相似,但又在更高的效率下解决了其不支持跨进程读写等弊端。
2.深入解析阿里巴巴路由框架ARouter 源码
组件化被越来越多的Android项目采用,而作为组件化的基础------路由也是重中之重。因此详细的分析阿里巴巴开源的路由框架ARouter。从源码的角度解释为什么这样使用,以及避免做什么,让你使用地更加顺滑。
3.深入解析AsyncTask 源码(一款 Android 内置的异步任务执行库)
AsyncTask 是 Android SDK 中提供的一个用于执行异步任务的框架,在 Android 兴起的早期被广泛使用,但如今已经被 RxJava、协程等新兴框架所取代。虽然它存在着一些不足,但我们还是可以尝试了解一下它的实现原理以及存在的不足。
4.深入解析Volley 源码(一款 Google 推出的网络请求框架)
Volley 是 Google 开发的一款网络请求框架,目前已停止更新。虽然目前大家的关注焦点都在 Retrofit、OkHttp 等第三方网络请求框架,团队的项目中所用的也是这两个框架,但 Volley 中还是有非常多优秀的设计思想值得我们去学习的。
5.深入解析 Retrofit源码
在Andrroid开发中,网络请求十分常用,而在Android网络请求库中,Retrofit是当下最热的一个网络请求库。
6.深入解析OkHttp 源码
OkHttp是一个处理网络请求的开源项目,是Android端最火热的轻量级框架,由移动支付Square公司贡献用于替代HttpUrlConnection和Apache HttpClient。随着OkHttp的不断成熟,越来越多的Android开发者使用OkHttp作为网络框架。
作为 Android开发者,大家肯定都知道大名鼎鼎的butterknife。它大大的提高了开发效率,虽然在很早之前大家就开始使用它了,但是只知道是通过注解的方式实现的,却一直没有仔细的学习下大牛的代码。所以有必要系统的分析下 butterknife的实现原理。
8.深入解析Okio源码(一套简洁高效的 I/O 库)
Okio 中有两个非常重要的接口------Sink 以及 Source,它们都继承了 Closeable,其中 Sink 对应了我们原来所使用的 OutputStream,而 Source 则对应了我们原来所使用的 InputStream。
Okio 的入口就是Okio 类,它是一个工厂类,可以通过它内部的一些 static 方法来创建 Sink、Source 等对象。
9.深入解析SharedPreferences源码
SharedPreference 是一个 Android 开发自带的适合保存轻量级数据的 K-V 存储库,它使用了 XML 的方式来存储数据,比如我就经常用它保存一些如用户登录信息等轻量级数据。
10.深入解析EventBus 源码
EventBus 是一个 Android 事件发布/订阅框架。
传统的事件传递方式包括:Handler(消息处理机制,一般用于更新UI)、BroadCastReceiver(广播接收者)、Interface 回调。
EventBus优点:
- Activity、Fragment、Service与线程之间的通讯是很常见的,EventBus正好可以屏蔽一些线程切换问题,简单地实现发布订阅功能。
- 代码简洁,使用简单,并将事件发布和订阅充分解耦。
11.Android 自定义注解初探
由于之前用到的很多开源框架如 GreenDao、EventBus、ButterKnife、ARouter 等都使用了自定义注解,因此有必要去研究一下自定义注解。
12.View 的工作机制源码分析
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
w-1719095247765)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取