JVM
JVM的结构
volatile
内存模型
主内存 工作内存
GC
Android
绘制流程
ViewRootImpl.performTraversals()
同步消息屏障
ViewRootImpl 将遍历 view 树包装成一个 Runnable 并抛到 Choreographer, 在抛之前会向主线程消息队列中抛同步屏障
同步屏障也是一个 Message,只不过 target 等于null
取下一条 message 的算法中,若遇到同步屏障,则会越过同步消息,向后遍历找第一条异步消息找到则返回(Choreographer 抛的异步消息),若没有找到则会执行 epoll 挂起
当执行到遍历 View 树的 runnable 时,ViewRootImpl 会移除同步屏障
Choreographer
将和 ui 相关的任务与 vsync 同步的一个类。
每个任务被抽象成 CallbackRecord,同类任务按时间先后顺序组成一条任务链 CallbackQueue。四条任务链存放在 mCallbackQueues[] 数组结构中
触摸事件,动画,View 树遍历都会被抛到 Choreographer,并被包装成 CallbackRecord 并存入链式数组结构,当 Choreographer 收到一个 Vsync 就会依次从输入,动画,绘制这些链中取出任务执行
当 vsync 到来时,会向主线程抛异步消息(执行 doFrame)并带上消息生成时间,当异步消息被执行时,从任务链上摘取所有以前的任务,并按时间先后顺序逐个执行。
绘制模型
1.软件绘制 2.硬件加速绘制
应用冷启动流程
Surface
它是原始图像缓冲区的一个句柄。即raw buffer的内存地址,raw buffer是保存像素数据的内存区域,通过Surface的canvas 可以将图像数据写入这个缓冲区
Surface类是使用一种称为双缓冲的技术来渲染
这种双缓冲技术需要两个图形缓冲区GraphicBuffer,其中一个称为前端缓冲区frontBuffer,另外一个称为后端缓冲区backBuffer。前端缓冲区是正在渲染的图形缓冲区,而后端缓冲区是接下来要渲染的图形缓冲区,当vsync到来时,交换前后缓冲区的指针
SurfaceFlinger
SurfaceFlinger 是由 init 进程启动的运行在底层的一个系统进程,它的主要职责是合成和渲染多个Surface,并向目标进程发送垂直同步信号 VSync,并在 vsync 产生时合成帧到frame buffer
Surfaceview
一个嵌入View树的独立绘制表面,他位于宿主Window的下方,通过在宿主canvas上绘制透明区域来显示自己
虽然它在界面上隶属于view hierarchy,但在WMS及SurfaceFlinger中都是和宿主窗口分离的,它拥有独立的绘制表面,绘制表面在app进程中表现为Surface对象,在系统进程中表现为在WMS中拥有独立的WindowState,在SurfaceFlinger中拥有独立的Layer,而普通view和其窗口拥有同一个绘制表面
TextureView
SurfaceView 拥有独立的绘制表面,而TextureView和View树共享绘制表面
TextureView通过观察BufferQueue中新的SurfaceTexture到来,然后调用invalidate触发View树重绘,如果有View叠加在TextureView上面,它们的脏区有交集,则会触发不必要的重绘,所以他的刷新操作比SurfaceView更重
界面卡顿
requestLayout() vs invalidate()
requestLayout: reMeasure reLayout reDraw
invalidate: reDraw
Binder
进程通信方式(IPC)
Bundle
Parcel
持久化方式
SharedPreferences Database onSavedInstance
Service
background service
foreground service
广播
BroadcastReceiver
消息机制
handler looper messageQueue
触摸事件
dispatchTouchEvent onTouchEvent
滑动冲突
recyclerview
view生命周期
Bitmap
ANR
恢复数据
onSaveInstanceState()+onRestoreInstanceState():会进行序列化到磁盘,耗时,杀进程依然存在
Fragment+setRetainInstance():数据保存在内存,配置发生变化时数据依然存在,但杀进程后数据不存在
进程优先级
LruCache
内部是一个 LinkedHashMap。LinkedHashMap 维护了一个队列,每次访问 LinkedHashMap 中的元素时,都会将该元素移动到队列的队尾。
当 LruCache 中缓存的元素超过了缓存大小时,会从 LinkedHashMap 队列的队头开始移除元素。
LinkedHashMap 对元素的引用是强引用,被移除的元素在下一次 GC 时可以被回收。
启动优化
Lifecycle
Lifecycle LifecycleOwner LifecycleObserver
LiveData
ViewModel
viewModel
编译打包流程
launch mode
standard singleTop singleTask singleInstance
android:taskAffinity
Context
Context ContextImpl ContextWrapper ContextThemeWrapper
Java
ArrayMap & HashMap
SparseArray & HashMap
泛型
java对象生命周期
类加载
类构造顺序
WeakHashMap
LinkedHashMap
ThreadLocal
存储 Thread 的私有数据
内存泄漏
引用
异常
注解
OOM类型
内存优化
equals()
默认实现使用 “==”
如果根据 equals 方法两个对象相等,则对这两个对象调用 hashCode 方法必须产生相同的整数结果。
不要求如果两个对象根据 equals 方法不相等,则对这两个对象中的每一个调用 hashCode 方法必须产生不同的整数结果。然而,应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。
hashCode()
每当在 Java 应用程序执行期间对同一对象多次调用 hashCode 方法时,只要对象上的 equals 比较中使用的信息没有被修改,hashCode 方法就必须始终返回相同的整数。 从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。