数据结构
二叉树的前中后序遍历
算法
网络
三次握手四次挥手
get和post的区别
http和https的区别
设计模式
六大原则
常用的几种设计模式
单例设计模式
java基础
八种数据类型
String、StringBuffer、StringBuilder
=和equals
泛型擦除
extends和super的区别
四种引用
hashmap
hashMap存数据的过程
hashMap解决冲突
hashMap和hashTable的区别
hashMap和LinkedHashMap的区别
如何保证线程安全
集合
ArrayList和LinkedList
ArrayList扩容
java多线程
线程和进程的区别
线程状态
线程状态转换及控制
sleep和wait的区别
锁
synchronized
synchronized的原理
synchronized与Lock的区别
死锁产生的条件
CAS乐观锁
原子性(synchronized + Lock)
可见性(synchronized + volatile + lock)
有序性(volatile)
volatile的两大特性(主存+禁止指令重排序)
synchronized和volatile的区别
线程池
创建线程池的7个参数
线程池的工作流程
五种线程池
1、newSingleThreadExecutor() : 1个核心线程 + 0个非核心线程 + 无界的队列
2、newFixedThreadPool():固定的核心线程 + 0个非核心线程 + 无界的队列
3、newCachedThreadPool(): 0个核心线程 + 无限的非核心线程 + 直接提交的队列
4、newScheduledThreadPool(): 线程池大小为1 + 等待队列
5、newSingleThreadScheduledExecutor(): 固定的核心线程 + 无限的非核心线程 + 等待队列
阻塞队列类型(无界的 + 直接提交的 + 等待的)
AsyncTask
AsyncTask是串行的还是并行的
AsyncTask的原理
AsyncTask的缺陷
HandlerThread
HandlerThread的原理
IntentService
IntentService的原理
IntentService的使用场景
java虚拟机
java虚拟机和Davik虚拟机的区别
内存区域
java内存区域
回收机制
哪些对象可以被回收
可以作为GC Roots的对象包括哪些
- 虚拟机栈中 引用的对象
- 本地方法栈中 引用的对象
- 方法区中类静态属性 引用的对象
- 方法区中常量 引用的对象
采用什么样的方式回收
何时回收这些对象
类加载
类加载器分类
类加载过程(加载、验证、准备、解析、初始化、使用、卸载)
双亲委派模型
为什么要双亲委派
handler
handler原理
子线程能不能new一个handler?为什么主线程可以?
一个线程会有几个Looper,几个handler,几个MessageQueen对象?
创建Message的几种方式及区别
MessageQueue是什么数据结构?
阻塞唤醒机制
当MessageQueue中没有即时执行的任务时,会阻塞在MessageQueue.next()方法中的nativePollOnce()方法中,此时线程会释放CPU进入休眠状态,就将Looper.loop()阻塞,直到下个任务的执行时间到达或者出现某些特殊的情况再将其唤醒,从而避免资源的浪费。
epoll机制: 在native层会有一个读取端和一个写入端,当有消息发送过来的时候会去唤醒读取端,然后进行消息发送与处理,没消息的时候是处于休眠状态,所以不会阻塞。
ThreadLocal原理
每一个Thread线程都会拥有自己的一个成员变量ThreadLocalMap,该变量默认为空(实际是ThreadLocal的静态内部类,只是Thread持有引用)。
当往ThreadLocal存数据时,调用的是ThreadLocal的set方法,该方法先拿到当前线程的ThreadLocalMap实例,然后以当前threadLocal实例为key把数据存进该map中。
当取数据时,一样拿到当前线程的ThreadLocalMap实例,并以当前threadLocal实例为key从里面拿出数据。
looper是如何区分多个handler的?
为什么主线程不会因为Looper.loop()里的死循环卡死?
App进程中是需要死循环的,如果循环结束的话,App进程就结束了。
首先,Looper.loop()的阻塞和UI线程上执行耗时操作导致卡死是完全的两回事。
Looper上的阻塞,前提是没有输入事件,MessageQueue 为空(有可能有延时的消息),Looper空闲状态,线程进入阻塞,释放CPU执行权,等待唤醒。
UI耗时导致卡死,前提是要有输入事件,MessageQueue 不为空,Looper正常轮询,线程并没有阻塞,但是该事件执行时间过长,然后就ANR异常了。
Looper.quit/quitSafely的区别?
handler 有哪些发送消息的方法
Handler.postDelayed后消息队列有什么变化,假设先postDelayed 10s, 再postDelayed 1s,怎么处理这2条消息?
Handler.post(Runnable)和Handler.sendMessage方法有什么区别?
Handler如何与Looper关联的?
Handler如何实现线程的切换?
当在A线程中创建Handler的时候,同时创建Looper和MessageQueue,Looper在A线程中调用loop()进入一个 无限的for循环,从MessageQueue中取消息;
当B线程调用Handler发送一个message的时候,会通过msg.target.dispatchMessage(msg);将message插入到Handler对应的MessageQueue中;
Looper发现有message插入到MessageQueue中,便取出message执行相应的逻辑,因为Looper.loop()是在A线程中启动的,所以则回到了A线程,达到了从B线程切换到A线程的目的。
IdleHandler是什么
IdleHanlder的使用场景
同步屏障机制
handler内存泄漏
handler内存泄漏引用关系
事件分发
事件是先到DecorView还是先到Window?
为什么DecorView就走了两次?
onTouch 和onTouchEvent 的区别?
点击事件被拦截,但是想传到下面的View,如何操作?
同时对父 View 和子 View 设置点击方法,优先响应哪个?
ACTION_CANCEL什么时候触发,触摸button然后滑动到外部抬起会触发点击事件吗,再滑动回去抬起会么?
在ViewGroup.dispatchTouchEvent中消费ACTION_DOWN事件,ACTION_UP事件是怎么传递?
在 ViewGroup 中的 onTouchEvent 中消费 ACTION_DOWN 事件, ACTION_UP事件是怎么传递?
Activity ViewGroup和View都不消费ACTION_DOWN,那么ACTION_UP 事件是怎么传递的?
View的绘制
Activity界面的显示流程
ActivityThread.handleLaunchActivity
->ActivityThread.performLaunchActivity
->Activity.attach
->完成DecorView的创建
->ActivityThread.handleResumeActivity
->Activity.onResume
->ViewRootImpl.performTraversals。
performTraversals方法主要执行了3个方法,分别是performMeasure、performLayout、performDraw,在其方法的内部又会分别调用View的measure(测量)、layout(布局)、draw(绘制)方法。
Measure
子View创建MeasureSpec的规则是什么?
单一View的measure过程(具体方法)
measure():基本测量逻辑的判断 + 调用下一个方法
onMeasure():调用后面两个方法
getDefaultSize():根据View宽/高的测量规格计算View的宽/高值
setMeasureDimension(): 存储测量后的子View宽/高
ViewGroup的measure过程(具体方法)
measure()--->onMeasure()--->measureChildren()--->measureChild()--->getChildMeasureSpec()--->setMeasuredDimension()
为什么要重写onMeasure?
问: 自定义View wrap_content不起作用,而且是起到与match_parent(填充父容器)相同作用,为什么?
1.getDefaultSize(): 当View的测量模式是AT_MOST(wrap_content)或EXACTLY(match_parent)时,大小都会被设置成MeasureSpec的specSize
2.getChildMeasureSpec():子View的MeasureSpec值是根据子View的布局参数(LayoutParams)和父容器的MeasureSpec值计算得来,子View MeasureSpec在属性被设置为wrap_content或match_parent时,specSize被设置成 parenSize = 父容器当前剩余空间大小
解决: 重写onMeasure()设置一个默认值。
layout
单一View的layout过程(具体方法)
仅计算本身View的位置: Layout()、onLayout()、setFrame()
ViewGroup的layout过程(具体方法)
1.计算自身的位置layout()
2.遍历子View、计算子View的位置 & 设置( (复写)ViewGroup.onLayout()、子View.layout()、子View.onLayout() )
- 如此不断循环,最终确定所有子View在父容器的位置,即layout过程完毕
单一View的draw过程(具体方法)
- 开始绘制
- draw: 绘制View自身
- drawBackgroud(): 绘制View自身的背景
- onDraw(): 绘制View自身的内容
- dispatchDraw():绘制子View(空实现,因为没有子View)
- onDrawScrollBars():绘制装饰
- 结束绘制
ViewGroup的draw过程(具体方法)
dispatchDraw() 调用draw()、drawBackgroud()、onDraw()、dispatchDraw()、onDrawScrollBars()
View和surfaceView的区别
getWidth()方法和getMeasureWidth()区别
requestLayout()、invalidate() 和 postInvalidate() 方法的区别?
IPC机制
Serializable和Parchlable区别
开启多进程会出现的问题
几种进程间通信方式
管道、消息队列、共享内存、套接字、信号量、信号
为何新增binder来作为主要的IPC方式
binder工作原理
-
Binder 驱动在内核空间创建一个数据接收缓存区。
-
在内核空间开辟一块内核缓存区,建立内核缓存区和数据接收缓存区之间的映射关系,以及数据接收缓存区和接收进程用户空间地址的映射关系。
-
发送方进程通过系统调用 copyfromuser() 将数据 copy 到内核空间的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信
AIDL
性能优化
启动优化
启动分类
几种启动时间统计方法
一些启动优化方案
内存泄漏
什么是内存泄漏
一些内存泄漏场景
内存检测分析工具
内存溢出
什么是内存溢出
图片的内存优化
内存抖动
什么是内存抖动
如何避免内存抖动
ANR
什么是ANR
ANR有几种类型
造成ANR的原因及解决办法
ANR如何定位
进程保活
进程优先级
进程回收策略
如何提高进程优先级
进程被杀死后拉活方案
布局优化
布局优化方法
包体积优化
APK体积优化方法
网络优化
网络优化方法
电量优化
电量优化手段
LeakCanary
LeakCanary原理
Lecanary的Idle机制
EventBus
EventBus的实现原理
根据事件类型找到所有订阅的类对象和其对应的事件方法(发送事件,取消注册)
根据类对象找到该类中的所有参数类型(取消注册)
okHttp
okHttp的7个拦截器
应用、RetryAndFollowUp、Bridge、Cache、Connect、网络、CallServer
addInterceptor与addNetworkInterceptor的区别
Retrofit
使用Retrofit的七个步骤
Retrofit原理解析
Glide
图片框架对比
自己写个图片加载框架,会考虑哪些问题
异步加载、切换线程、缓存、防止OOM、内存泄漏、列表滑动加载的问题
Glide图片加载流程
Glide如何处理生命周期
Glide的缓存
LruCache
LinkedHashMap
大图加载
Rxjava
Rxjava线程切换
Rxjava背压(Flowable)
Rxjava常用操作符
如何解决Rxjava内存泄漏
map和flatmap的区别
热修复
类加载流程
热修复的原理
插件化
插件化原理
组件化
组件化的原理
Activity
activity的生命周期(正常、跳转、跳到透明主题、点击Home键、弹出dialog、屏幕方向切换)
四种启动模式
onNewIntent()方法什么时候执行?
Service
启动Service的两种方式的区别
Service 的 onStartCommand 方法有几种返回值?各代表什么意思?
如何提高service的优先级?
广播
广播的分类
静态注册广播与动态注册广播的区别
BroadcastReceiver 与 LocalBroadcastReceiver 有什么区别?
ContentProvider
ContentProvider的作用
contentprovider初始化时机
简单framework
AMS WMS PMS
系统启动流程
1.启动电源以及系统启动
2.引导程序BootLoader
3.Linux内核启动
4.init进程启动
5.zygote进程启动
6.SystemServer进程启动
7.Launcher启动
activity启动流程
-
Launcher进程请求AMS
-
AMS发送创建应用进程请求 (AMS与Zygote进程建立Socket连接)
-
Zygote进程接受请求并孵化应用进程
-
应用进程启动ActivityThread
-
应用进程绑定到AMS
-
AMS发送启动Activity的请求
-
ActivityThread的Handler处理启动Activity的请求