Android 面试总结
第一部分 Java部分
1 hashmap和hashtable的区别 详情请参考源码
父类不同
查询方式不同
Hashmap 不是线程安全的而hashtable是线程安全的
Hashmap key value 允许使用null值 那是因为hashmap默认把null的hash值设置成了0 而hashtable不允许key value使用null值
Hashmap默认长度是16 每次增长2倍 hashtable默认长度是11 每次增加2n+1
Hashmap源码解析:
数组和链表如何工作 ----- 当执行put方法的时候 把key的hashcode值通过位运算转变成数组下标
2 array list和 linkedlist的区别 详情请参考源码
Arraylist 是以数组的形式存储数据 在查询的情况下 array list 效率比较快一点
Linkedlist以单链表的形式存储数据 在插入和删除的情况下 linkedlist效率会快一点
3 Java四种引用方式 弱引用和软引用区别
使用软引用 Java GC工作的时候 如果内存空间够的话 不会回收 只有内存空间不够的情况下 才会回收 而使用弱引用的话 只要GC一工作便会回收
第二部分 Android
1 Activity的生命周期
oncreate 当activity创建的时候执行此方法
onstart 当activity开始运行 但是用户看不见的时候执行此方法
onresume 当activity处于前台 用户能看见了 执行此方法
onpause 当activity处于后台执行方法
onstart 当activity暂停 执行此方法
onrestart 当actvitiy 从后台重新回到前台执行此方法。
Ondestroy 当activity 销毁执行此方法
Activity 的启动方式
Standard 默认启动方式 每次都会创建一个新的activity
SingeTop 栈顶复用模式 当activity处于栈顶的时候 不执行 oncreate onstart 方法 执行 onnewIntert 方法 如果不处于栈顶 则会重新创建一个activity实例
SingeTask 当activity处于栈顶的时候不执行 oncreate onstart方法 执行 onnewIntent 当activity 不在栈顶 他会把位于他上头的activity都出栈 自己到栈顶
Singeinstance 单例模式的 直接创建一个新的任务栈 并且把activity实例放在任务栈中
2 Fragment 的生命周期
3 Service 生命周期
4 Android设计模式
单例模式 观察者模式 代理模式
5 JVM
6 HTTP协议网络请求
http发送请求分为七个步骤
第一步建立连接
第二部客户端向服务器发送http请求
第三步客户端发送请求头信息 最后发送一个空的请求体代表请求头信息发送完毕 如果是post提交 则会继续发送请求体
第四步 服务器端应答 应答的第一部分是版本号和http状态码
第五步 发送应答头信息 最后发送一个空白行代表发送结束
第六步 web服务器发送数据以Content-type 应答头信息 开始的 然后跟一个空行 再以下是响应的数据
第七步 web服务器关闭TCP连接,一旦web服务器向客户端发送完消息之后它就要关闭TCP请求。
三次握手
第一次握手 建立连接,将SYN设置为1 seq设置x 然后客户端进入等待状态
第二次握手 服务器端收到客户端的SYN设置,需要对SYN值进行确认,设置ACK的值为 seq+1,同时自己还要发送SYN值 设置为1 ,seq设置成Y,此时服务器进入等待状态
第三次握手 客户端收到服务器的SYN+ACK报文段,然后将ACK设置成seq+1 seq = z一并发给服务器
为了防止已失效的连接请求报文段突然又传送到服务端,因而产生错误 所以才需要三次握手。
四次挥手
五层模型
应用层(http) 传输层(tcp) 网络层(ip) 链路层 物理层
http和https的区别
Socket是应用层与TCP/IP协议通信的一个抽象层,它是一组接口,
7多线程 线程池
8线程安全 volatile关键字
Synchronized (新块儿奈斯特) 同步代码块 同步方法
Lock 是一个接口 当发生异常的时候不会主动释放锁 必须通过lock.unlock释放
Synchronized是Java的关键字 当发生异常的时候会主动释放锁
Volatile
9 HandlerThread IntentService
IntentServic继承自service。其实内部是以handler和handlerThread实现的 在oncreate方法里创建一个HandlerTread
然后在里头创建了一个名为ServiceHandler的hanlder 然后把ServiceHandler和HandlerThread对应的子线程进行绑定
通过onstartcommand方法 内部调用onstart方法把消息传递给Intent,依次插入到工作队列中,并逐个发送给onhandlerIntent方法
HandlerThread是Google帮我们封装好的 可以执行多个耗时操作 里面采用的是Handler Looper方式实现的
使用HandlerThread必须先调用start方法 调用start方法之后线程会交给虚拟机调度 虚拟机自行调用run方法
10 Handler讲解。
Handler 负责处理消息
MessageQueue 存放消息 先进先出原则
Looper 轮询消息队列里有没有消息 如果有消息就取出来
主线程的Looper在activityThread已经创建好了 所以主线程创建handler的时候不需要手动创捷looper
当在activity主线程创建handler的时候 首先会先查找有没有looper
子线程中使用handler要创建Looper对象 调用Looper.prepare方法创建Looper 调用Looper.loop方法来轮询消息队列
当Handler发送消息的时候会调用 MessageQueue 的 enqueuemessage方法来向消息队列里头插入消息 当通过looper.loop 循环消息的时候 调用MessageQueue.next 方法来获取消息
Looper存储在ThreadLocal里头 ThreadLocal是线程本地存储区,每个线程都有自己私有的线程存储区,不同线程之间不能访问彼此的线程存储区 简称TLS区域
当handler执行sendMessage方法时 经过层层调用一直到MessageQueue的enqueueMessage方法往消息队列里插入数据 然后Loope通过MessageQueue.next方法取出消息
为什么主线程loop死线程不会导致ANR
MessageQueue.next方法会获取到第一个消息 来进行对比 看看到没到执行时间如果没到执行时间就等待 会放到Linux层等待 释放当前线程
10.1 ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。换句话说ThreadLocal是线程隔离的工具类
一个Thraed只对应一个Looper , 因为MessageQueue是在Looper里头创建的所以也只有一个
因为Looper的prepare方法里头调用了ThreadLocal.get方法来保证唯一性 如果之前已经创建过 就抛出异常
11 当Android中发生handler泄露怎么办
发生泄漏的情况一般是handler在执行耗时任务的时候 activity已经处于关闭状态 这个时候 由于handler还没有运行完毕 还持有activity的引用 所以没法回收activity
解决办法 当activity 执行 ondestroy方法的时候 关闭handler 把handler设置成null
第二种办法就是 把当前handler设置成静态的 在handler里对当前activity使用弱引用
12 Android中使用cookie
13 mvc mvp mvvm
MVP全称是 model view presenter
优点 视图(View) 和 model 完全分离 逻辑代码全部放再presenter里头 可以更高效的使用model
缺点 presenter与view交互过于频繁 view发生改变 presenter也要随之发生改变
Mvc 有点 耦合度低 重用性高
在MVP框架里 model和view并不直接交互 而是使用presenter做为两者之间的桥梁
14 okhttp
15 EnevtBus 工作原理
16 rxjava
17 view的绘制过程
onMeause onLayout onDraw
18 Android 事件分发
Activity PhoneWindow DecorView ViewGroup View
先判断父容器是否拦截事件,没有拦截再继续向下分发,分发的时候找触摸点在哪个View 找的过程就是分发的过程,找到dispatchTouchEvent为true的View
冲突解决方法
1 内部拦截 在子view进行处理的就 叫内部拦截
2 外部拦截 在父容器处理的就叫外部拦截
19 进程保活 以及进程拉活
进程保活 1像素保活
前台进程保活
进程拉货
双进程守护
20 进程优先级
前台进程 可见进程 服务进程 后台进程 空进程
21 进程之间的通信 Aidl builder
22 内存泄漏以及内存优化
集合泄漏
单例模式泄漏
Handler泄漏 在执行一个耗时任务的时候 当Acitivty关闭,但是线程并没有关闭 这个时候就会发生内存泄漏
非静态内部类泄漏 因为非静态内部类会持有外部类的引用
Static 泄漏 尽量不要用静态变量 它的生命周期伴随整个App的生命周期
内存优化
布局优化 尽可能的少使用嵌套布局
Bitmap的优化
数据缓冲优化
Handler优化
23 liveData hook技术
24 屏幕适配
比例缩放
25 数据持久化
MKV 不使用IO方式 使用的是MMAP
Linux可以将虚拟内存与磁盘上的对象关联起来 。以初始化这个虚拟内存的内容 这个过程就叫做 MMAP。
MMAP 不经过内核空间。通过对磁盘文件的映射,操作内存就相当于操作文件。