更新记录
- 2020-09-06:阅读自定义View,更新Scroller
一、Android相关
Handler
主要回答
MessageQueue
中的Message
排序的依据,以及为什么不能msg.when
用System.currentTimeMills
进行赋值?MessageQueue
的when
= SystemClock#uptimeMillis() 与 delayMillis 之和;SystemClock#uptimeMillis()
是一个表示当前时间的一个相对时间,它代表的是 自系统启动开始从0开始的到调用该方法时相差的毫秒数
✅ 为什么MessageQueue
用链表的形式存储?
本质山这个问题就是:数组和链表的区别在哪里?Handler 的使用场景正是频繁插入,但是每次都只取最前面的消息处理,所以对于这种情况,天然的应该使用链表来进行存储而不是数组
Fragment
✅ Android Fragment 从源码的角度去解析(下)
fragment的
add
和replace
的区别(add
就是添加到container
中,replace
会先移除,后添加),以及如何实现显示一个,隐藏其他fragment -》(getFragments()获取到所有的fragment,然后调用hide方法隐藏,最后调用要显示XXFragment的show()方法);
回答关于如何正确使用
findFragmentByTag()
,以及为什么跟ViewPager
配合时不要使用findViewByTag()
。
方案:基于
FragmentManager
管理所有Fragment
的返回按键,需要Fragment
实现一个接口
Bitmap
对于BitmapFactory.Options参数进行了讲解,同时还提供了一套如何加载大图的方案 -> inJustDecode + inSampleSize
✅ Android Bitmap变迁与原理解析(4.x-8.x)
4.x-8.x Bitmap像素数据是保存在java堆中,会发生OOM;8.0x是保存在Native中,不容易发生OOM,根据作者的测试,8.0之后Bitmap消耗内存可以无限增长,直到耗尽系统内存。
2020.03.31 一刷,没看懂~ 等待二刷
Activity
关于
taskAffinity
的作用以及搭配各种启动flag后会出现什么问题
- Activity生命周期源码分析 -> todo:总结各个阶段做了什么
Activity
在调用onDestroy
方法后就被销毁了吗?其实没有,如果翻看源码,我们可以发现,Activity
的onDestory
方法没有一句代码是把Activity
置为空,onDestroy
只是把ViewRootImpl
和DecorView
解绑了,最终还是AMS
收拾残局。
✅ Android可见APP的不可见任务栈(TaskRecord)销毁分析
2020.04.01一刷:对于单栈(TaskRecord)应用,在前台的时候,所有界面都不会被回收,只有多栈情况下,系统才会回收不可见栈的Activity。回收不可见Task的时机:Java使用内存超过3/4的时候;
ViewStub
✅
mmap原理解析
1.11 LowMemoryKiller
- 被后台杀死后,Android应用如何重新走闪屏逻辑
- Android后台杀死系列之四:Binder讣告原理
- Android后台杀死系列之一:FragmentActivity及PhoneWindow后台杀死处理机制
- Android后台杀死系列之二:ActivityManagerService与App现场恢复机制
- Android后台杀死系列之三:后台杀死原理LowMemoryKiller(4.3-6.0)
Android窗口管理
非常好的一篇文章,收放自如。不仅介绍了
Window
添加的流程,对于应用层
的添加流程很详细,对于WMS
的添加流程也给出了流程图。此外,自己最大的收获是对于流程中的各个类之间的协作和作用更加清楚了,很赞!
✅ Android图形系统(二)-DecorView布局加载流程
DecorView
加载流程,主要分为四步:
1、初始化DecorView(installDecor,包括解析窗口的theme和feature属性,也是在这一步)
2、解析xml,并添加到decorView中
3、在
handleResumeActivity
中设置DecorView
可见,同时将它跟ViewRootImpl
进行绑定,通过view.assignParent(this)
方法
✅ Android窗口机制(五)最终章:WindowManager.LayoutParams和Token以及其他窗口Dialog,Toast
理清窗口的不同类型:
Toast
是系统窗口;PopupWindow
和Dialog
是子窗口(依附于activity)
帮助理清了
Window
的移除逻辑
- Android窗口管理分析(4):Android View绘制内存的分配、传递、使用
- Android窗口管理分析(3):窗口分组及Z-order的确定
- Android窗口管理分析(2):WindowManagerService窗口管理之Window添加流程
- Android窗口管理分析(1):View如何绘制到屏幕上的主观理解
- Android图形显示系统(一)
- 刘望舒的WindowManager系列
- Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程
- Android图形系统概述
- Android图形系统之VSync
- Android图形系统系统篇之Gralloc
输入系统
Toast
✅[ 从 Toast 显示原理初窥 Android 窗口管理
总结:notificationManager -> handler.post -> wms.addView()
Binder
- 听说你 Binder 机制学的不错,来解决下这几个问题(三)
- 听说你 Binder 机制学的不错,来解决下这几个问题(二)
- 听说你Binder机制学的不错,来解决下这几个问题(一)
- Android Binder原理(一)学习Binder前必须要了解的知识点
AMS
自定义view
- 【透镜系列】看穿 > NestedScrolling 机制 >
- 【透镜系列】看穿 > 触摸事件分发 >
- Android实现圆弧滑动效果之ArcSlidingHelper篇
- View篇:玩一下自定义ViewGroup
✅ Android进阶之旅 - 自定义View篇 ✅你真的了解Android ViewGroup的draw和onDraw的调用时机吗
理解了
ViewGroup
的draw
和onDraw
的调用时机,以及ViewGroup
什么情况下会进行绘制,这主要取决于mPrivateFlag
,如果设置了setWillNotDraw(true)
,那么会调用dispatchDraw()
进行绘制子类,自己不绘制;但是,如果设置了setWillNotDraw(false)
,还要看view.isOpque()
这个判断实心的方法返回值,如果返回true,那么也不会绘制自己,只要返回
false,才会调用
drawBackGround和
onDraw()`方法。
关于
View.post()
这个方法,在没看文章之前,我的推测是底部用的是Handler
,至于这个handler
应该是来自于DecorView
,但是具体post
的时机自己猜测不出。看完文章,知道了,底层的的确用的还是handler
,post
的时机是在ViewRootImpl
的performTraversal
,并且在performMeasure()
等方法前,原因是,必须要等这条消息执行完了,才会去执行消息队列里的消息,所以在之前还是之后发送并没有多大关系。 所以,View.post
方法获取View
的宽高是可靠的,因为此时已经执行完成。
扩展:获取View
宽高的几种方式:
- 通过onWindowFocusChanged方法
- 通过View.post()来实现
- 通过ViewTreeObserver的OnGlobalLayoutListener回调
Scroller
二、第三方开源库
RxJava
第一部分讲解了
Observable.create
方法的流程,总结数据源创建的流程,以及如何通过subscribeActual
方法将源头和终点关联起来。
第二部分介绍了操作符
map
的源码以及线程切换的原理。map
的原理是在onNext
方法中,先调用了自己的apply
方法,之后再调用下游的onNext
方法。线程切换的实现原理是:在subscribeActual
方法中调用scheduler.scheduleDirect
方法,通过创建如IOWorker
等线程调度类,将方法放置在不同的线程执行。等到调用onNext
方法的时候,同样也会创建MainThreadWorker
,重新把方法放置在主线程运行。
OkHttp
✅[为何 response.body().string() 只能调用一次?
只能读取一次是因为读取完毕后
OkHttp
会关掉数据流连接,至于这么设计的原因主要是考虑实际应用时,多次读取数据的可能性较小,所以设计成一次性流读取
目前看过觉得讲解的最好的系列
上一个OkHttp系列没有分析重试机制,所以要补上,自己根据理解画了一下流程图
Retrofit
✅Android:手把手带你 深入读懂 Retrofit 2.0 源码
以上两篇文章都用于搭框架,越是漂亮的源码在跟踪的时候会越容易迷失,第一篇文章会很长,不用一次性看完,先看完框架 重点:理清
Call
、CallAdapter
、Converter
、CallBackExecutor
这几个之间的作用和调用流程就可以继续往下了
✅Android:手把手带你 深入读懂 Retrofit 2.0 源码
以上两篇文章都有对源码以及源码中涉及模式的分析,文章都很长,但是好在排版都很好,看起来也不会太枯燥
EventBus
✅[ EventBus源码解析
非常详细的源码解析文,代码注释非常多
✅[ Android 框架学习3:从 EventBus 中学到的精华
Eentbus优点:在
Activity
与Activity
或者Service与activity传递大数据时非常有用,缺点:不易管理、调试困难
ARouter
三、Java基础
HashMap
✅HashMap初始容量为什么是2的n次幂及扩容为什么是2倍的形式
原因在于:向集合中添加元素时,会使用
(n - 1) & hash
的计算方法来得出该元素在集合中的位置: 1、符号&是按位与的计算,这是位运算,计算机能直接运算,特别高效; 2、(n-1)
的2进制也就是1111111***111
这样形式的,这样与添加元素的hash
值进行位运算时,能够充分的散列
SparseArray
四、其他
混合开发
原生和前端的交互有两种方式:url scheme以及JavaScriptCore(在Android中是addJavascriptInterface) - H5调Android-原生通过addJavascriptInterface注册,然后H5直接调用
Android调H5-原生通过loadUrl来调用H5,4.4及以上还可以通过evaluateJavascript调用
性能优化
这个系列对Systrace的介绍很详细,而且还覆盖了很多干货,比如:图形系统、
SurfaceFlinger
通过将
Activity
的theme
设置成windowBackground @null
以及canvas.drawXX
每次都会绘制多一层,这两个点对自己有启发
插件化
字节码插桩
ANR
主要介绍了如何分析traces文件(anr原因,cpu使用率,JVM参数讲解等),属于工具性讲解。缺少ANR深层原因的分析,比如:系统是如何监控ANR的?