Android 面经收集大全
注意: 本文是通过阅读大量的博文以及其他论坛的精彩好文简化版随手录,如有侵权马上删除!
持续更新~~
文字多,难免有些错别字,最近时间忙,后续尽快更改,望谅解
文章目录
- Android 面经收集大全
- 简述
- 数据库
- 1.数据库的索引和实现原理
- 2.手撕`MySQL`分组查询
- 3.数据库中的事务理解
- Linux
- 1.`Linux`中断命令
- 操作系统
- 1.操作系统线程和进程的同步机制和通信机制
- 2.什么是缓存溢出
- 3.操作系统分页分段管理
- 4.CPU时间片
- 5.线程池
- Java基础
- 1.`Java`四种引用
- 2.`Java synchronized`的类锁和对象锁
- 3.JavaGC机制 [hotspot为例]
- 4.哪些对象可以作为GC ROOTS对象
- 5.volatile关键字和synchronize关键字
- 6.Java内存模型的可见性,重排序,原子性
- 计算机网络
- 1.`OSI`网络模型 [七层]
- 2.`TCP/IP`模型 [四层]
- 3.网络设别工作在那一层
- 4.``HTTP,HTTPS,HTTP1,HTTP2`
- 5.三次握手及其相关
- 6.https加密过程
- 7.在浏览器中键入URL时会发生什么
- 8.get各post的区别
- 设计模式
- 1.手写Java双重检验的单列模式
- 2.设计模式原则
- Android框架使用
- 1.`Glide`的使用 [加载图片]
- 2. `EventBus`的使用
- 3.`Rxjava`通讯机制
- Android基础
- 1.你常用的组件有哪些
- 2.`Android`四大组件
- 3. 自定义view
- 4.约束布局
- 5.Serializable和Parcelable的理解和区别
- 6.假如手机只有10M内存,想要申请1M的内存是否一定成功
- 算法题
- 1.归并排序
- 2. 汉诺塔
- 3.数组反转
- 4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)
- 5.数组反转,给一个target整数,每target长度反转一次
- 6.最长连续子序列 O(n)
- 7.数组反转,给一个target整数,每target长度反转一次
- 8.连续最大总和
- 9.最长公共子序列长度
- 10.两个字符串是否是重排序
- 11.字符串轮转
- 12.最近公共祖先
- 13.第k个丑数
- 14.到处弟k个节点
- Android 面经收集大全
- 简述
- 数据库
- 1.数据库的索引和实现原理
- 2.手撕`MySQL`分组查询
- 3.数据库中的事务理解
- Linux
- 1.`Linux`中断命令
- 操作系统
- 1.操作系统线程和进程的同步机制和通信机制
- 2.什么是缓存溢出
- 3.操作系统分页分段管理
- 4.CPU时间片
- 5.线程池
- Java基础
- 1.`Java`四种引用
- 2.`Java synchronized`的类锁和对象锁
- 3.JavaGC机制 [hotspot为例]
- 4.哪些对象可以作为GC ROOTS对象
- 5.volatile关键字和synchronize关键字
- 6.Java内存模型的可见性,重排序,原子性
- 计算机网络
- 1.`OSI`网络模型 [七层]
- 2.`TCP/IP`模型 [四层]
- 3.网络设别工作在那一层
- 4.``HTTP,HTTPS,HTTP1,HTTP2`
- 5.三次握手及其相关
- 6.https加密过程
- 7.在浏览器中键入URL时会发生什么
- 8.get各post的区别
- 设计模式
- 1.手写Java双重检验的单列模式
- 2.设计模式原则
- Android框架使用
- 1.`Glide`的使用 [加载图片]
- 2. `EventBus`的使用
- 3.`Rxjava`通讯机制
- Android基础
- 1.你常用的组件有哪些
- 2.`Android`四大组件
- 3. 自定义view
- 4.约束布局
- 5.Serializable和Parcelable的理解和区别
- 6.假如手机只有10M内存,想要申请1M的内存是否一定成功
- 算法题
- 1.归并排序
- 2. 汉诺塔
- 3.数组反转
- 4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)
- 5.数组反转,给一个target整数,每target长度反转一次
- 6.最长连续子序列 O(n)
- 7.数组反转,给一个target整数,每target长度反转一次
- 8.连续最大总和
- 9.最长公共子序列长度
- 10.两个字符串是否是重排序
- 11.字符串轮转
- 12.最近公共祖先
- 13.第k个丑数
- 14.到处弟k个节点
简述
<<<<<<< HEAD
但不仅限于Android方面,希望通过此方式把自己的知识台阶一步一步搭起,最后通向offer的大门,知识汇聚,知识分享,开源的力量是无穷尽的,也祝大家早些时日提取自己心满意足的offer.
PS: 本收集属于对其他各大技术论坛大佬精美好文的简短总结
数据库
1.数据库的索引和实现原理
- 索引就是一个查找问题,索引是一个排序的数据结构,实现通常是B树及其变种
- 优点
- 唯一索引,保证每一行数据的唯一性
- 加快检索速度
- 加速表之间的连接
- 减少分组和排序时间
- 使用优化隐藏器提高性能
- 缺点
- 创建和维护耗时
- 占据更多的物理空间
- 增删改需要动态维护索引
- 在什么列上需要创建索引
- 经常搜索的列
- 主键列 [唯一性]
- 经常连接的列 [外键]
- 经常需要排序的列
- 经常使用在where子句中的列 [条件判断]
- 什么列不需要索引
- 查询少的列
- 只有很少数据值的列
- 定义数据类型很大的列 [比如text image bit]
- 修改性能大于检索性能的列
- 存储结构 [B树,B+树,红黑树]
2.手撕MySQL分组查询
- 按照某个字段进行分组
group by
-
having
指定查询的条件,对分组的内容尽心过滤 - 单独使用
group by
- 结合聚合函数使用
- 结合having一起使用
having和where的区别:
都是根据条件进行过滤,
having后面可以跟随聚合函数
3.数据库中的事务理解
- 事务? 更新各种数据项的一个程序执行单元 [操作的集合: 这个集合从开始事务到提交事务]
- 保持数据库的一致性,可以恢复数据
- 程序操作数据的一个隔离
- 特性
- 原子性
要么全部执行,要么不执行
- 一致性
完整约束状态一致转移
- 隔离性
事物之间不影响
- 持久性
一旦提交,永久保存
- 隔离级别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nukikaE4-1581727051667)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581680424542.png)] - 隔离 并发控制
- 乐观并发控制
一开始以乐观的心态认位没有冲突,直到真的有冲突了才去解决问题
- 悲观并发控制
一开始悲伤地假定必然会出现冲突,使用锁使其串行执行
- 锁 <还有一控制并发的就是 时间戳>
- 共享锁
有了共享锁只能在拥有共享锁
- 排他锁
明显的排斥,不再拥有其他锁
- 死锁
多个事务持有锁,相互等待无法执行
- 饥饿
一直加共享锁,不曾获得排他锁
Linux
1.Linux中断命令
- 中断
- CPU暂停当前的程序执行,转去处理突发事件,处理完后返回原程序继续执行
- 中断请求线: 中断唯一标识的数值
- 中断处理函数:内核执行对应的处理函数,中断的优先级最高
- 分类
- 中断<外部中断或异步中断>: 外设向处理器发出中断请求
- 异常<内部中断或同步异常>: 处理器执行指令错误
- 终端命令
-
CTRL+C
强制中断程序执行 -
CTRL+z
任务中断,进程挂起 -
CTRL+d
特殊字符 EOF
-
CTRL+\
退出 -
kill pid
扩展: 后台进程管理命令:
-
jobs
查看当前有多少在后台运行的命令 -
fg
将后台的命令调至前台执行 -
bg
将后台暂停的命令继续执行
操作系统
1.操作系统线程和进程的同步机制和通信机制
- 同步机制
- 临界区
- 互斥量
- 信号量
PV操作
关键词解释: 进程调度
- 事件
- 通讯机制
- 无名管道
- 消息队列
- 信号量
- 共享内存
2.什么是缓存溢出
- 缓冲区
- 写入的缓冲区的数据超出缓冲区的大小,溢出的数据覆盖合法的数据 [溢出]
- 一段可读可写的内存区域
- 危害
- 程序崩溃,拒绝服务
- 执行恶意代码
- 缓冲区攻击 [驱使操作系统执行恶意的代码]
- 原因
- 没有检查用户的合法输入
3.操作系统分页分段管理
- 存储器层次结构
- 高速缓存
- 主存
- 磁盘
- 内存管理方式
- 连续分配存储管理
- 单一连续
- 系统区
- 用户区
- 分区管理 [分时系统,程序并发执行,引入问题使内存碎片]
- 固定分区 [限制并发执行程序的数目]
- 动态分区 [没有内碎片,有外碎片,算法复杂]
- 分区分配算法
- 最先适配 :从头查找符合条件的第一个分区
- 下次适配:从上一次分配分区开始向下查找第一个符合的分区
- 最佳适配:查找大小相差最小的分区
- 最坏适配:查找最大的空闲分区
- 内存紧缩 [占用的分区移动到一端,其余空闲分区合成一个新的空闲分区]
- 覆盖技术 [较小的可用内存运行较大的程序 ,必要数据常驻内存,可选部分在外存,使用公共内存]
- 交换技术 [不执行的程序暂时送到外存,装入新的程序执行]
- 交换和覆盖的区别
- 交换不需要覆盖结构
- 交换在进程和作业之间
- 覆盖在同一作业或进程中
- 覆盖只能覆盖无关的程序段
- 页式存储
- 原理
- 逻辑地址划分为固定大小的页
- 物理内存划分为相同大小的页框
- 将页转入页框
- CPU实现逻辑地址和物理地址的映射
- 优点
- 没有页外碎片,也内碎片比较小
- 程序不必连续存放
- 方便更改程序占用控件大小
- 缺点
- 一时刻装入整个程序
- 数据结构
- 进程表: 逻辑地址到物理地址的映射
- 物理页面表:描述物理内存的分配状况
- 请求表: 描述进程表的大小和位置
- 地址变换
- 使用逻辑页号最终找到物理地址
- 段式存储
- 原理
- 将程序地址空间划分为多个段
- 每个段分配一个连续的分区
- 各个段可以不连续在不同分区
- 动态分区管理物理内存
- 优点
- 分别编写和编译源程序的一个文件
- 没有内存碎片,外存碎片可以内存紧缩消除
- 内存共享
- 缺点
- 进程全部装入内存
- 数据结构
- 进程段表: 进程地址的各段
- 系统段表: 描述系统所有已分配的段
- 空闲段表:内存中所有空闲段
- 地址交换: 段表地址寄存器完成
- 区别
- 分页系统管理的需要
- 分段满足用户的需要
- 页使信息的物理单位
- 段是信息的逻辑单位
- 页大小固定,固定值由系统决定
- 段长度不固定,大小由用户程序决定
- 页式地址空间是一维的
- 段地址空间是二维的 <段名,段内地址>
- 段表比页表短
4.CPU时间片
- CPU分配给每个程序的时间,允许该程序运行的时间
- 程序或者线程在时间片结束前还在运行,CPU会强行把程序推出CPU,随机挑一个线程或者程序进来执行下一个时间片
- 若程序或者线程在时间片结束前结束,CPU立马挑选一个程序或者线程来执行,这样就不会浪费CPU资源,提高利用率
- 时间片的大小通常为10-100ms
时间片轮询调度算法 抢占式的
5.线程池
- 达到线程的复用,减少创建和销毁的开销
- 优点
- 核心
Java基础
1.Java四种引用
目的: 决定对象的生命周期利用JVM
进行垃圾回收
- 强引用
- 软引用
- 弱引用
- 虚引用
2.Java synchronized的类锁和对象锁
- 对象锁
- 仅仅有关键字synchronized
- 也称实例锁
- 防止其他线程同时访问该实例的synchronized方法块
- 每个实例拥有自己的监视块
- 类锁
- static synchronized
- 也称全局锁,
- 控制类的所有实例的并发访问 [限制都线程该该类的所有实例同时访问jvm中对应的代码块]
- 所有实例公用一个监视块
- demo
- 总结
3.JavaGC机制 [hotspot为例]
- 堆
- 新生代
- eden region
- 分配所得空间较大
- 垃圾回收时,eden和survivor存活的对象被复制一遍到两一个survivor中
- from survivor region
- survivor空间不够依赖老生代
- to survivor region
- 老生代
- 保存大对象
- 这个区满了就报出
outofmemory
异常
- 永久代 [一般不会被回收]
- 方法去
- 判断一个类是否无用,满足下列条件
- 类的所有实例被回收,队中不存在该类的任何实例
- 该类的classloader被回收
- 该类的java.lang.class没有任何地方被引用
- 什么时候执行GC操作
- Eden区空间不足,执行较小的GC
- 老年代空间不足,执行重大的GC
- 老年代连续可用空间小于新生代对象总大小,指向Full GC
- 对象的年龄计数器判断对象应该在新生代还是老生代 <判断依据有两个: 最大年龄 ; 相同年龄对象大小总和占比重>
- 确定对象是否不可用
- 引用计数法
判断对象是否可用
- 可达性分析
判断对象是否存活
- 垃圾收集算法
- 标记清除 : 标记需要回收的对象,清除被标记对象占用的内存 <缺点: 内存碎片严重>
- 复制算法: 内存一分为二,一部分用于直接存储对象,另一部分备用,解决内存碎片问题 <缺点:实际可用内存缩短一半>
- 标记整理:对象移动到内存的一端,清除边缘对象,标记的对象时需要移动的
- 分代收集:
- 根据对象的生命周期收集垃圾对象
- eden和另一个surivivor的存活对象复制到两一个surivivor中,再清除eden和surivivor区域
4.哪些对象可以作为GC ROOTS对象
GC会收集那些不是GC roots且没有被GC roots引用的对象
- JVM中的栈引用对象
- 方法区中的类静态属性引用对象
- 方法区中常量引用对象(final常量)
- 本地方法栈jni引用对象
5.volatile关键字和synchronize关键字
- volatile
- 使变量具有可见性 [可见性:我理解是有点同步的意思,就是一个变量被修改,最新的值立马更新到主存供其他线程使用最新之,以至于不会继续使用旧的值]
- 直接读写内存
- 禁止指令重排 [指令重排: 处理器优化代码,可能改变代码执行顺序,但在单线程下不会改变执行结果, 多线程上则不能]
- synchronize
- 既保证可见性 [同一时刻只有一个线程获得锁然后执行代码,释放锁之前将最新之刷新到主存]
- 也保证原子性 [要么执行,要么不执行]
6.Java内存模型的可见性,重排序,原子性
- 可见性:使用的是直接缓存到CPU中
- 重排序:改变指令执行顺序,优化代码,但不会改变执行结果
- 原子性 :操作单一不可见
计算机网络
1.OSI网络模型 [七层]
- 物理层
- 数据链路层
- 网络层
- 传输层
- 会话层
- 表示层
- 应用层
2.TCP/IP模型 [四层]
- 应用层: 传输协议
- 传输层: TCP UDP
- 网络层: IP ICMP
- 物理链路层: 根据需要选择不同的物理链路
3.网络设别工作在那一层
- 网卡
物理层 - 中继器
物理层 [复原网络中的信号,从新发送到其他网段] - 集线器
物理层 [连接各个物理设备] - 网桥
数据链路层的MAC子层上<介质访问控制层> [网段中相同协议传输数据包] - 交换机
数据链路层 [和网桥类似的功能] - 路由器
网络层 [分组转发和路由]
4.``HTTP,HTTPS,HTTP1,HTTP2`
-
HTTP
- 明文方式发送内容
- 不提供加密
- 80端口
- 无状态连接
-
HTTPS
- 在HTTP基础上加入了SSL协议<通讯加密,依靠证书验证服务器的身份>
- 用途
- 保证数据传输的安全
- 确认网站的真实性
- 需要申请证书
- 443端口
- 短连接
- 缺点
- 握手阶段耗时
- 缓存效率相对HTTP底
- ssl证书需要钱
- ssl证书需要绑定ip,不能在同一个ip上绑定多个域名
- 加密范围有限
-
HTTP1.0
- 无状态 <不记录客户端过去的请求>
- 无连接 <处理完任务马上断开连接>
-
HTTP1.1
- 持久连接 <默认keep-alive,避免重新连接和释放>
- 管道化
- 增加缓存
- host字段
- 断点传输
- <不允许同时存在两个响应>
-
HTTP2.0
- 二进制分帧
- 流:双向字节流
- 消息:逻辑对应的数据帧集合
- 帧:最小单位,标记当前帧所属的流
- 多路复用
- TCP连接 <承载任意数量的双向数据流>
- 数据流以消息的形式发送 <可乱序发送,后根据帧头部标识的所属流进行重装>
- 并行传输
- 头部压缩
- HTTP1.x头部数据以纯文本形式传输
- HTTP2.0使用encoder,双方各自缓存一份header Fiedls <注意使缓存,重复利用,避免重传>
- 服务器推送
- 无需客户端明确请求,主动向客户端推送资源
-
HTTP2和HTTPS
的关系
5.三次握手及其相关
- 为何连接
- 客户端和服务器的内存里保存对方的一份信息
- 双方需要交换参数 <参数放在TCP头部>
- 可靠,面向连接,字节流,传输层服务
- 三次握手连接 <两次初始化序列号,两次确认> ,四次握手关闭
- 序列号
- 作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段
- 标识符
-
ACK
确认 -
RST
重连 -
SYN
初始化序列号 -
FIN
发送方结束向对方发送数据
6.https加密过程
- 对称加密
- 加密和解密使用同一个密钥
- 非对称加密
- 私钥: 不让其他人知道 [解密]
- 公钥:任何人可以知道 [加密]
- 加密过程
- 非对称加密
- 结合 对称加密
- 结合 数字证书
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-efge8kmr-1581727051672)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581601486036.png)]
7.在浏览器中键入URL时会发生什么
一个完整的http请求
- 域名解析
- 查找浏览器本身的dns缓存,找IP地址和域名的映射表
- 操作系统的dns缓存
- 本地服务器dns缓存
- 根域名服务器发起请求
- 顶级域名服务器发起请求
- 权限服务器发起请求
- 得到IP地址
- 逐级返回IP地址给浏览器
- 发起HTTP请求
- 到传输层,选择TCP或者UDP,封装HTTP请求
- 到网络层,IP协议封装IP地址为IP数据报,使用arp协议
- 数据链路层,封装成mac帧
- 服务器响应请求资源
- 断开连接
8.get各post的区别
get
post
设计模式
1.手写Java双重检验的单列模式
- 侧重考点就是在如何实现双重验证
双重验证的逐渐演化过程
1.单线程适用
缺点:只能适用与单线程
2.多线程适用 [适用synchronized方法]
缺点:每次调用方法都需要同步的代价,实际上是只有if语句需要同步
3.降低同步调用代价 [适用synchronized代码块]
缺点: 当两个线程进入if判断之后,有一个线程进入了同步代码块,还有另外一个线程在同步块外,if语句内等待,所以当同步块线程创建完对象之后退出同步块,另一个线程没有再次判断instance是否为null
4.双重检查 [在创建对象之前再加一个if判断null]
缺点:理想很美好,现实很骨感,不能保证在单处理器和多处理器上顺序执行,因为内存模型写入是无序的
5.解决无序写入问题 [双重同步代码块]
6.优化无序写入
7.考虑到内存模型和写入顺序,最终选择方案
- 使用static关键字的单例模式
- 使用同步方法
2.设计模式原则
开闭原则: 对扩展开放,对修改关闭
- 单一原则: 每个类尽可能单一职责
- 里氏替换: 父类可以出现的地方,子类可以替换
- 依赖倒置:依赖于抽象而不是具体,面更象接口编程
- 接口隔离: 接口中不存在子类用不到却必须实现的方法
- 迪米特法则:最少知道,具体逻辑封装在方法内部,只与直接的朋友通讯
- 合成复用: 稍用继承,多用合成和聚合
常用设计模式
简单工厂模式 <缺点 :依赖工厂类,没有面向接口编程>
- 简单工厂 <传入创建对象的指令 [字符串] >
- 创建接口
- 创建实现类
- 工厂类
- 工厂方法 <改进传入指令错误的问题>
- 一个工厂有具体的方法创建具体的对象
- 静态工厂 <解决创建工厂类的实例问题,直接调用方法创建实例>
- 简单的在 工厂方法上添加static关键字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hHf2NgcM-1581727051674)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581665500037.png)]
工厂方法模式
- 创建工厂接口
- 多个工厂实现类 <依赖到接口了,改变了>
- 一个接口,new谁的实现类接口回调就是谁的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUOrJzpI-1581727051675)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581665732430.png)]
抽象工厂模式 <易混淆与 工厂方法模式 >
- 区别
- 工厂方法
工厂中的一条生产线
,生产专一的产品 - 抽象工厂
真正的工厂
生产多中产品
单例模式
见上文
原型模式
- 对象的 复制克隆出一个新的对象
- 实现
- 实现
clone able
接口 - 腹泻clone方法
- 深复制
无论是基本类型还是引用类型,都是全新的创建
- 浅复制
基本类型重新创建,引用类型指向原来的对象
适配器模式
- 类适配
功能扩展到另一个类
继承被扩展的类,实现新的接口 - 对象适配 <这个最多> 新类组合被扩展的类,重写的方法内调用组合类的方法
- 接口适配 不需要实现一个接口的所有方法,分离一部分方法到新的接口
装饰模式
- 装饰类持有扩展类的实例 <组合>
- 内部调用组合对象的方法达到功能扩展
代理模式 <经典的MVP模式p层>
观察者模式 <发布订阅>
Android框架使用
1.Glide的使用 [加载图片]
- 特点
- 可以加载
gif
动图 - 播放本地
MP4
- 加载默认图片
.fallback(id)
- 重置大小
.resize(int,int)
- 裁剪图片
.fitcenter()
- 缩放图片
thumbnail(0.1f)
- 圆角图片
bitmaptransform(new )
- 缓存 [自定义缓存]
diskCacheStrategy
- 修改缓存大小,位置,图片质量
- 请求优先级,加载图片的优先级
.priority(int)
- 加载网络图片
Glide.with(context).load(url).into(imageview)
- 加载文件
- 根据id加载
- uri加载
2. EventBus的使用
- 发布订阅<观察者模式>的事件总线
- 作用
- 简化组件之间通讯 [两个fragment之间的]
- 组件和后台线程间的通讯 [网络请求]
- 使用
-
event
事件 [任意类型的对象] -
subscribe
订阅者 [指定线程模型] -
publisher
发布者 [任意线程位置发送事件post方法
]
- 线程模型
-
posting
事件发布和事件接受在同一个线程 [默认] <避免执行耗时操作,因会阻塞事件传递> -
main
在ui线程中处理事件,不能耗时操作,ui线程本来就不能耗时操作 -
background
在子线程中处理事件 [一般是网络请求等耗时操作] <子线程发布事件就在子线程中处理事件,ui线程发布事件就创建新的子线程处理事件> -
async
无论在哪个线程发布事件,都将新建子线程处理事件
3.Rxjava通讯机制
- 扩展的观察者模式
-
observable
被观察者 -
observer
观察者 -
subscribe
订阅
- 事件回调方法
-
onnext
<类似于点击> -
oncompleted
事件队列完成 -
onerror
错误
- 使用
- 创建观察者
- [重写三个回调方法]
observer
- <这个的一个抽象类
subscriber
> 用法一致 - [onstart方法在所在线程处理事件,不能更新ui,更新ui需要用doonsubscribe方法中]
- 创建被观察者
observable
- 从写call方法,内部调用
subscriber.onnext() oncompleted()
等方法,一次执行事件 - 还有
just() from()
-
subscribe
订阅事件
- 把观察者和被观察者关联起来
observable.subscribe(observer);
-
Action0() Action1()
将对象打包起来内部打包了不同的回调方法 -
scheduler
线程控制器 [指定一段代码运行在什么样的线程下]
- 默认下: 在哪一个线程调用subscriber()就在该线程产生事件,就在该线程消费事件
-
immediate()
默认情况,在当前线程运行 -
newThread()
总是创建新的线程执行代码 -
io
io操作[网络,数据库,文件读取],内部实现有一个无数量上限的线程池 -
computation
CPU计算密集型 -
mainthread
Android主线程
- 变换
- 加工整个序列,转换成不同的事件序列
-
Func1
具有返回值的包装 -
map
flatmap
Android基础
1.你常用的组件有哪些
常用组件 | 用途 |
text view | 文本显示 |
edit text | 注册框,搜索框 |
button | 登录按钮 |
float action button <悬浮按钮> | flutter中印象深刻的一个按钮,登录 |
recycle view | list view少用了,动态列表 |
switch | 白天和黑夜模式的开关 |
scroll view | 上下滑动 |
fragment | 结合view page使用布局切换 |
image view | 显示各种图片 |
check box | 订单的选择 |
web view | 新闻网页的显示 |
progress bar | 加载进度 |
spinner | 下拉消息选项 |
rating bar | 订单评价 |
search view | 搜索框 |
constraint layout | 最喜欢的一个布局 |
linear layout | 常常使用等比例均分的属性 |
grid layout | 搜索预选择的格子 |
horizontal scroll view | 横向布局 ,切换页面 |
tool bar | 首页的顶部文字显示 |
bottom navigation view | 主界面的底部导航栏 |
view | 一些分割线 |
2.Android四大组件
- activity
- 单独的窗口
- 通过intent通讯
- 必须在
AndroidManifest.xml
配置文件中声明
- service
- 用于后台完成用户操作
- 启动,调用
startService()
- 与启动服务的组件无关
- 可以无限期运行
- 销毁服务需要调用
stopSelf() 或者 stopService()
- 绑定,调用
bindService()
- 与绑定服务的组件相关联
- 配之文件需要声明service
- content provider
- 不同程序之间的数据共享
- 使用uri标实数据集
- broadcast receiver
- 对感兴趣的外部事件进行接受并作出响应
- 可以启用一个activity或者service来响应接收到的信息
- 也可以使用notificationmanager通知用户
- 动态注册
- 生命周期随注册的activity共存亡
- 静态注册
- 生命周期独立于程序
3. 自定义view
- 自绘控件
- 继承view或者view group
- 自定义view属性
- 在res/values创建xml定义属性
- 在构造方法中获取 自定义的属性
- 重写onDraw方法
- [可选]重写onMesure方法
- 控件组合
4.约束布局
- 特点
- 百分比适配屏幕和控件
- 解决布局嵌套过多问题
- 添加动画
- 支持代码布局控件(不需要写xml)
- 和相对布局的区别
5.Serializable和Parcelable的理解和区别
序列化: 将一个对象转换成可存储和可传输的状态
- serializable
- Java自带
- 易产生大量的临时对象,容易GC
- 保证数据很好的持久性 <另外那个都东西是在内存中的啊>
- 一般还是使用这个的多,方便和持久
- 代码量少
- 使用反射,序列化过程满
- parcelable
- Android专用
- 将一个完整的对象分解,分解后的每一部分都是intent支持的基本数据类型
- 数据都在内存中,是内存的时候是很推荐的
- 效率高 <毕竟是专款专用>
6.假如手机只有10M内存,想要申请1M的内存是否一定成功
内存分配规则
算法题
1.归并排序
2. 汉诺塔
递归实现
非递归实现
3.数组反转
4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)
5.数组反转,给一个target整数,每target长度反转一次
6.最长连续子序列 O(n)
7.数组反转,给一个target整数,每target长度反转一次
8.连续最大总和
9.最长公共子序列长度
10.两个字符串是否是重排序
直接sort排序一次,比较是否相同
异或相同,取模相同
multiset集合<一个是字母排序好,一个是统计字母个数>
11.字符串轮转
两个连接字符串中查找是否含有字串
12.最近公共祖先
13.第k个丑数
双重循环,选择乘3 5 7 中最小的一个
14.到处弟k个节点
双指针走向
栈的特性
Android 面经收集大全
注意: 本文是通过阅读大量的博文以及其他论坛的精彩好文简化版随手录,如有侵权马上删除!
持续更新~~
文章目录
- Android 面经收集大全
- 简述
- 数据库
- 1.数据库的索引和实现原理
- 2.手撕`MySQL`分组查询
- 3.数据库中的事务理解
- Linux
- 1.`Linux`中断命令
- 操作系统
- 1.操作系统线程和进程的同步机制和通信机制
- 2.什么是缓存溢出
- 3.操作系统分页分段管理
- 4.CPU时间片
- 5.线程池
- Java基础
- 1.`Java`四种引用
- 2.`Java synchronized`的类锁和对象锁
- 3.JavaGC机制 [hotspot为例]
- 4.哪些对象可以作为GC ROOTS对象
- 5.volatile关键字和synchronize关键字
- 6.Java内存模型的可见性,重排序,原子性
- 计算机网络
- 1.`OSI`网络模型 [七层]
- 2.`TCP/IP`模型 [四层]
- 3.网络设别工作在那一层
- 4.``HTTP,HTTPS,HTTP1,HTTP2`
- 5.三次握手及其相关
- 6.https加密过程
- 7.在浏览器中键入URL时会发生什么
- 8.get各post的区别
- 设计模式
- 1.手写Java双重检验的单列模式
- 2.设计模式原则
- Android框架使用
- 1.`Glide`的使用 [加载图片]
- 2. `EventBus`的使用
- 3.`Rxjava`通讯机制
- Android基础
- 1.你常用的组件有哪些
- 2.`Android`四大组件
- 3. 自定义view
- 4.约束布局
- 5.Serializable和Parcelable的理解和区别
- 6.假如手机只有10M内存,想要申请1M的内存是否一定成功
- 算法题
- 1.归并排序
- 2. 汉诺塔
- 3.数组反转
- 4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)
- 5.数组反转,给一个target整数,每target长度反转一次
- 6.最长连续子序列 O(n)
- 7.数组反转,给一个target整数,每target长度反转一次
- 8.连续最大总和
- 9.最长公共子序列长度
- 10.两个字符串是否是重排序
- 11.字符串轮转
- 12.最近公共祖先
- 13.第k个丑数
- 14.到处弟k个节点
- Android 面经收集大全
- 简述
- 数据库
- 1.数据库的索引和实现原理
- 2.手撕`MySQL`分组查询
- 3.数据库中的事务理解
- Linux
- 1.`Linux`中断命令
- 操作系统
- 1.操作系统线程和进程的同步机制和通信机制
- 2.什么是缓存溢出
- 3.操作系统分页分段管理
- 4.CPU时间片
- 5.线程池
- Java基础
- 1.`Java`四种引用
- 2.`Java synchronized`的类锁和对象锁
- 3.JavaGC机制 [hotspot为例]
- 4.哪些对象可以作为GC ROOTS对象
- 5.volatile关键字和synchronize关键字
- 6.Java内存模型的可见性,重排序,原子性
- 计算机网络
- 1.`OSI`网络模型 [七层]
- 2.`TCP/IP`模型 [四层]
- 3.网络设别工作在那一层
- 4.``HTTP,HTTPS,HTTP1,HTTP2`
- 5.三次握手及其相关
- 6.https加密过程
- 7.在浏览器中键入URL时会发生什么
- 8.get各post的区别
- 设计模式
- 1.手写Java双重检验的单列模式
- 2.设计模式原则
- Android框架使用
- 1.`Glide`的使用 [加载图片]
- 2. `EventBus`的使用
- 3.`Rxjava`通讯机制
- Android基础
- 1.你常用的组件有哪些
- 2.`Android`四大组件
- 3. 自定义view
- 4.约束布局
- 5.Serializable和Parcelable的理解和区别
- 6.假如手机只有10M内存,想要申请1M的内存是否一定成功
- 算法题
- 1.归并排序
- 2. 汉诺塔
- 3.数组反转
- 4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)
- 5.数组反转,给一个target整数,每target长度反转一次
- 6.最长连续子序列 O(n)
- 7.数组反转,给一个target整数,每target长度反转一次
- 8.连续最大总和
- 9.最长公共子序列长度
- 10.两个字符串是否是重排序
- 11.字符串轮转
- 12.最近公共祖先
- 13.第k个丑数
- 14.到处弟k个节点
简述
<<<<<<< HEAD
但不仅限于Android方面,希望通过此方式把自己的知识台阶一步一步搭起,最后通向offer的大门,知识汇聚,知识分享,开源的力量是无穷尽的,也祝大家早些时日提取自己心满意足的offer.
PS: 本收集属于对其他各大技术论坛大佬精美好文的简短总结
数据库
1.数据库的索引和实现原理
- 索引就是一个查找问题,索引是一个排序的数据结构,实现通常是B树及其变种
- 优点
- 唯一索引,保证每一行数据的唯一性
- 加快检索速度
- 加速表之间的连接
- 减少分组和排序时间
- 使用优化隐藏器提高性能
- 缺点
- 创建和维护耗时
- 占据更多的物理空间
- 增删改需要动态维护索引
- 在什么列上需要创建索引
- 经常搜索的列
- 主键列 [唯一性]
- 经常连接的列 [外键]
- 经常需要排序的列
- 经常使用在where子句中的列 [条件判断]
- 什么列不需要索引
- 查询少的列
- 只有很少数据值的列
- 定义数据类型很大的列 [比如text image bit]
- 修改性能大于检索性能的列
- 存储结构 [B树,B+树,红黑树]
2.手撕MySQL
分组查询
- 按照某个字段进行分组
group by
-
having
指定查询的条件,对分组的内容尽心过滤 - 单独使用
group by
- 结合聚合函数使用
- 结合having一起使用
having和where的区别:
都是根据条件进行过滤,
having后面可以跟随聚合函数
3.数据库中的事务理解
- 事务? 更新各种数据项的一个程序执行单元 [操作的集合: 这个集合从开始事务到提交事务]
- 保持数据库的一致性,可以恢复数据
- 程序操作数据的一个隔离
- 特性
- 原子性
要么全部执行,要么不执行
- 一致性
完整约束状态一致转移
- 隔离性
事物之间不影响
- 持久性
一旦提交,永久保存
- 隔离级别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JkqlpozX-1581727052499)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581680424542.png)] - 隔离 并发控制
- 乐观并发控制
一开始以乐观的心态认位没有冲突,直到真的有冲突了才去解决问题
- 悲观并发控制
一开始悲伤地假定必然会出现冲突,使用锁使其串行执行
- 锁 <还有一控制并发的就是 时间戳>
- 共享锁
有了共享锁只能在拥有共享锁
- 排他锁
明显的排斥,不再拥有其他锁
- 死锁
多个事务持有锁,相互等待无法执行
- 饥饿
一直加共享锁,不曾获得排他锁
Linux
1.Linux
中断命令
- 中断
- CPU暂停当前的程序执行,转去处理突发事件,处理完后返回原程序继续执行
- 中断请求线: 中断唯一标识的数值
- 中断处理函数:内核执行对应的处理函数,中断的优先级最高
- 分类
- 中断<外部中断或异步中断>: 外设向处理器发出中断请求
- 异常<内部中断或同步异常>: 处理器执行指令错误
- 终端命令
-
CTRL+C
强制中断程序执行 -
CTRL+z
任务中断,进程挂起 -
CTRL+d
特殊字符 EOF
-
CTRL+\
退出 -
kill pid
扩展: 后台进程管理命令:
-
jobs
查看当前有多少在后台运行的命令 -
fg
将后台的命令调至前台执行 -
bg
将后台暂停的命令继续执行
操作系统
1.操作系统线程和进程的同步机制和通信机制
- 同步机制
- 临界区
- 互斥量
- 信号量
PV操作
关键词解释: 进程调度
- 事件
- 通讯机制
- 无名管道
- 消息队列
- 信号量
- 共享内存
2.什么是缓存溢出
- 缓冲区
- 写入的缓冲区的数据超出缓冲区的大小,溢出的数据覆盖合法的数据 [溢出]
- 一段可读可写的内存区域
- 危害
- 程序崩溃,拒绝服务
- 执行恶意代码
- 缓冲区攻击 [驱使操作系统执行恶意的代码]
- 原因
- 没有检查用户的合法输入
3.操作系统分页分段管理
- 存储器层次结构
- 高速缓存
- 主存
- 磁盘
- 内存管理方式
- 连续分配存储管理
- 单一连续
- 系统区
- 用户区
- 分区管理 [分时系统,程序并发执行,引入问题使内存碎片]
- 固定分区 [限制并发执行程序的数目]
- 动态分区 [没有内碎片,有外碎片,算法复杂]
- 分区分配算法
- 最先适配 :从头查找符合条件的第一个分区
- 下次适配:从上一次分配分区开始向下查找第一个符合的分区
- 最佳适配:查找大小相差最小的分区
- 最坏适配:查找最大的空闲分区
- 内存紧缩 [占用的分区移动到一端,其余空闲分区合成一个新的空闲分区]
- 覆盖技术 [较小的可用内存运行较大的程序 ,必要数据常驻内存,可选部分在外存,使用公共内存]
- 交换技术 [不执行的程序暂时送到外存,装入新的程序执行]
- 交换和覆盖的区别
- 交换不需要覆盖结构
- 交换在进程和作业之间
- 覆盖在同一作业或进程中
- 覆盖只能覆盖无关的程序段
- 页式存储
- 原理
- 逻辑地址划分为固定大小的页
- 物理内存划分为相同大小的页框
- 将页转入页框
- CPU实现逻辑地址和物理地址的映射
- 优点
- 没有页外碎片,也内碎片比较小
- 程序不必连续存放
- 方便更改程序占用控件大小
- 缺点
- 一时刻装入整个程序
- 数据结构
- 进程表: 逻辑地址到物理地址的映射
- 物理页面表:描述物理内存的分配状况
- 请求表: 描述进程表的大小和位置
- 地址变换
- 使用逻辑页号最终找到物理地址
- 段式存储
- 原理
- 将程序地址空间划分为多个段
- 每个段分配一个连续的分区
- 各个段可以不连续在不同分区
- 动态分区管理物理内存
- 优点
- 分别编写和编译源程序的一个文件
- 没有内存碎片,外存碎片可以内存紧缩消除
- 内存共享
- 缺点
- 进程全部装入内存
- 数据结构
- 进程段表: 进程地址的各段
- 系统段表: 描述系统所有已分配的段
- 空闲段表:内存中所有空闲段
- 地址交换: 段表地址寄存器完成
- 区别
- 分页系统管理的需要
- 分段满足用户的需要
- 页使信息的物理单位
- 段是信息的逻辑单位
- 页大小固定,固定值由系统决定
- 段长度不固定,大小由用户程序决定
- 页式地址空间是一维的
- 段地址空间是二维的 <段名,段内地址>
- 段表比页表短
4.CPU时间片
- CPU分配给每个程序的时间,允许该程序运行的时间
- 程序或者线程在时间片结束前还在运行,CPU会强行把程序推出CPU,随机挑一个线程或者程序进来执行下一个时间片
- 若程序或者线程在时间片结束前结束,CPU立马挑选一个程序或者线程来执行,这样就不会浪费CPU资源,提高利用率
- 时间片的大小通常为10-100ms
时间片轮询调度算法 抢占式的
5.线程池
- 达到线程的复用,减少创建和销毁的开销
- 优点
- 核心
Java基础
1.Java
四种引用
目的: 决定对象的生命周期利用JVM
进行垃圾回收
- 强引用
- 软引用
- 弱引用
- 虚引用
2.Java synchronized
的类锁和对象锁
- 对象锁
- 仅仅有关键字synchronized
- 也称实例锁
- 防止其他线程同时访问该实例的synchronized方法块
- 每个实例拥有自己的监视块
- 类锁
- static synchronized
- 也称全局锁,
- 控制类的所有实例的并发访问 [限制都线程该该类的所有实例同时访问jvm中对应的代码块]
- 所有实例公用一个监视块
- demo
- 总结
3.JavaGC机制 [hotspot为例]
- 堆
- 新生代
- eden region
- 分配所得空间较大
- 垃圾回收时,eden和survivor存活的对象被复制一遍到两一个survivor中
- from survivor region
- survivor空间不够依赖老生代
- to survivor region
- 老生代
- 保存大对象
- 这个区满了就报出
outofmemory
异常
- 永久代 [一般不会被回收]
- 方法去
- 判断一个类是否无用,满足下列条件
- 类的所有实例被回收,队中不存在该类的任何实例
- 该类的classloader被回收
- 该类的java.lang.class没有任何地方被引用
- 什么时候执行GC操作
- Eden区空间不足,执行较小的GC
- 老年代空间不足,执行重大的GC
- 老年代连续可用空间小于新生代对象总大小,指向Full GC
- 对象的年龄计数器判断对象应该在新生代还是老生代 <判断依据有两个: 最大年龄 ; 相同年龄对象大小总和占比重>
- 确定对象是否不可用
- 引用计数法
判断对象是否可用
- 可达性分析
判断对象是否存活
- 垃圾收集算法
- 标记清除 : 标记需要回收的对象,清除被标记对象占用的内存 <缺点: 内存碎片严重>
- 复制算法: 内存一分为二,一部分用于直接存储对象,另一部分备用,解决内存碎片问题 <缺点:实际可用内存缩短一半>
- 标记整理:对象移动到内存的一端,清除边缘对象,标记的对象时需要移动的
- 分代收集:
- 根据对象的生命周期收集垃圾对象
- eden和另一个surivivor的存活对象复制到两一个surivivor中,再清除eden和surivivor区域
4.哪些对象可以作为GC ROOTS对象
GC会收集那些不是GC roots且没有被GC roots引用的对象
- JVM中的栈引用对象
- 方法区中的类静态属性引用对象
- 方法区中常量引用对象(final常量)
- 本地方法栈jni引用对象
5.volatile关键字和synchronize关键字
- volatile
- 使变量具有可见性 [可见性:我理解是有点同步的意思,就是一个变量被修改,最新的值立马更新到主存供其他线程使用最新之,以至于不会继续使用旧的值]
- 直接读写内存
- 禁止指令重排 [指令重排: 处理器优化代码,可能改变代码执行顺序,但在单线程下不会改变执行结果, 多线程上则不能]
- synchronize
- 既保证可见性 [同一时刻只有一个线程获得锁然后执行代码,释放锁之前将最新之刷新到主存]
- 也保证原子性 [要么执行,要么不执行]
6.Java内存模型的可见性,重排序,原子性
- 可见性:使用的是直接缓存到CPU中
- 重排序:改变指令执行顺序,优化代码,但不会改变执行结果
- 原子性 :操作单一不可见
计算机网络
1.OSI
网络模型 [七层]
- 物理层
- 数据链路层
- 网络层
- 传输层
- 会话层
- 表示层
- 应用层
2.TCP/IP
模型 [四层]
- 应用层: 传输协议
- 传输层: TCP UDP
- 网络层: IP ICMP
- 物理链路层: 根据需要选择不同的物理链路
3.网络设别工作在那一层
- 网卡
物理层 - 中继器
物理层 [复原网络中的信号,从新发送到其他网段] - 集线器
物理层 [连接各个物理设备] - 网桥
数据链路层的MAC子层上<介质访问控制层> [网段中相同协议传输数据包] - 交换机
数据链路层 [和网桥类似的功能] - 路由器
网络层 [分组转发和路由]
4.``HTTP,HTTPS,HTTP1,HTTP2`
-
HTTP
- 明文方式发送内容
- 不提供加密
- 80端口
- 无状态连接
-
HTTPS
- 在HTTP基础上加入了SSL协议<通讯加密,依靠证书验证服务器的身份>
- 用途
- 保证数据传输的安全
- 确认网站的真实性
- 需要申请证书
- 443端口
- 短连接
- 缺点
- 握手阶段耗时
- 缓存效率相对HTTP底
- ssl证书需要钱
- ssl证书需要绑定ip,不能在同一个ip上绑定多个域名
- 加密范围有限
-
HTTP1.0
- 无状态 <不记录客户端过去的请求>
- 无连接 <处理完任务马上断开连接>
-
HTTP1.1
- 持久连接 <默认keep-alive,避免重新连接和释放>
- 管道化
- 增加缓存
- host字段
- 断点传输
- <不允许同时存在两个响应>
-
HTTP2.0
- 二进制分帧
- 流:双向字节流
- 消息:逻辑对应的数据帧集合
- 帧:最小单位,标记当前帧所属的流
- 多路复用
- TCP连接 <承载任意数量的双向数据流>
- 数据流以消息的形式发送 <可乱序发送,后根据帧头部标识的所属流进行重装>
- 并行传输
- 头部压缩
- HTTP1.x头部数据以纯文本形式传输
- HTTP2.0使用encoder,双方各自缓存一份header Fiedls <注意使缓存,重复利用,避免重传>
- 服务器推送
- 无需客户端明确请求,主动向客户端推送资源
-
HTTP2和HTTPS
的关系
5.三次握手及其相关
- 为何连接
- 客户端和服务器的内存里保存对方的一份信息
- 双方需要交换参数 <参数放在TCP头部>
- 可靠,面向连接,字节流,传输层服务
- 三次握手连接 <两次初始化序列号,两次确认> ,四次握手关闭
- 序列号
- 作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段
- 标识符
-
ACK
确认 -
RST
重连 -
SYN
初始化序列号 -
FIN
发送方结束向对方发送数据
6.https加密过程
- 对称加密
- 加密和解密使用同一个密钥
- 非对称加密
- 私钥: 不让其他人知道 [解密]
- 公钥:任何人可以知道 [加密]
- 加密过程
- 非对称加密
- 结合 对称加密
- 结合 数字证书
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RNGPGSwt-1581727052504)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581601486036.png)]
7.在浏览器中键入URL时会发生什么
一个完整的http请求
- 域名解析
- 查找浏览器本身的dns缓存,找IP地址和域名的映射表
- 操作系统的dns缓存
- 本地服务器dns缓存
- 根域名服务器发起请求
- 顶级域名服务器发起请求
- 权限服务器发起请求
- 得到IP地址
- 逐级返回IP地址给浏览器
- 发起HTTP请求
- 到传输层,选择TCP或者UDP,封装HTTP请求
- 到网络层,IP协议封装IP地址为IP数据报,使用arp协议
- 数据链路层,封装成mac帧
- 服务器响应请求资源
- 断开连接
8.get各post的区别
get
post
设计模式
1.手写Java双重检验的单列模式
- 侧重考点就是在如何实现双重验证
双重验证的逐渐演化过程
1.单线程适用
缺点:只能适用与单线程
2.多线程适用 [适用synchronized方法]
缺点:每次调用方法都需要同步的代价,实际上是只有if语句需要同步
3.降低同步调用代价 [适用synchronized代码块]
缺点: 当两个线程进入if判断之后,有一个线程进入了同步代码块,还有另外一个线程在同步块外,if语句内等待,所以当同步块线程创建完对象之后退出同步块,另一个线程没有再次判断instance是否为null
4.双重检查 [在创建对象之前再加一个if判断null]
缺点:理想很美好,现实很骨感,不能保证在单处理器和多处理器上顺序执行,因为内存模型写入是无序的
5.解决无序写入问题 [双重同步代码块]
6.优化无序写入
7.考虑到内存模型和写入顺序,最终选择方案
- 使用static关键字的单例模式
- 使用同步方法
2.设计模式原则
开闭原则: 对扩展开放,对修改关闭
- 单一原则: 每个类尽可能单一职责
- 里氏替换: 父类可以出现的地方,子类可以替换
- 依赖倒置:依赖于抽象而不是具体,面更象接口编程
- 接口隔离: 接口中不存在子类用不到却必须实现的方法
- 迪米特法则:最少知道,具体逻辑封装在方法内部,只与直接的朋友通讯
- 合成复用: 稍用继承,多用合成和聚合
常用设计模式
简单工厂模式 <缺点 :依赖工厂类,没有面向接口编程>
- 简单工厂 <传入创建对象的指令 [字符串] >
- 创建接口
- 创建实现类
- 工厂类
- 工厂方法 <改进传入指令错误的问题>
- 一个工厂有具体的方法创建具体的对象
- 静态工厂 <解决创建工厂类的实例问题,直接调用方法创建实例>
- 简单的在 工厂方法上添加static关键字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YeJSRQLL-1581727052505)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581665500037.png)]
工厂方法模式
- 创建工厂接口
- 多个工厂实现类 <依赖到接口了,改变了>
- 一个接口,new谁的实现类接口回调就是谁的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HyHsndx6-1581727052507)(C:\Users\Primer4\Desktop\AndroidTheInterview\TheInterviewExperienceOfAndroid\1581665732430.png)]
抽象工厂模式 <易混淆与 工厂方法模式 >
- 区别
- 工厂方法
工厂中的一条生产线
,生产专一的产品 - 抽象工厂
真正的工厂
生产多中产品
单例模式
见上文
原型模式
- 对象的 复制克隆出一个新的对象
- 实现
- 实现
clone able
接口 - 腹泻clone方法
- 深复制
无论是基本类型还是引用类型,都是全新的创建
- 浅复制
基本类型重新创建,引用类型指向原来的对象
适配器模式
- 类适配
功能扩展到另一个类
继承被扩展的类,实现新的接口 - 对象适配 <这个最多> 新类组合被扩展的类,重写的方法内调用组合类的方法
- 接口适配 不需要实现一个接口的所有方法,分离一部分方法到新的接口
装饰模式
- 装饰类持有扩展类的实例 <组合>
- 内部调用组合对象的方法达到功能扩展
代理模式 <经典的MVP模式p层>
观察者模式 <发布订阅>
Android框架使用
1.Glide
的使用 [加载图片]
- 特点
- 可以加载
gif
动图 - 播放本地
MP4
- 加载默认图片
.fallback(id)
- 重置大小
.resize(int,int)
- 裁剪图片
.fitcenter()
- 缩放图片
thumbnail(0.1f)
- 圆角图片
bitmaptransform(new )
- 缓存 [自定义缓存]
diskCacheStrategy
- 修改缓存大小,位置,图片质量
- 请求优先级,加载图片的优先级
.priority(int)
- 加载网络图片
Glide.with(context).load(url).into(imageview)
- 加载文件
- 根据id加载
- uri加载
2. EventBus
的使用
- 发布订阅<观察者模式>的事件总线
- 作用
- 简化组件之间通讯 [两个fragment之间的]
- 组件和后台线程间的通讯 [网络请求]
- 使用
-
event
事件 [任意类型的对象] -
subscribe
订阅者 [指定线程模型] -
publisher
发布者 [任意线程位置发送事件post方法
]
- 线程模型
-
posting
事件发布和事件接受在同一个线程 [默认] <避免执行耗时操作,因会阻塞事件传递> -
main
在ui线程中处理事件,不能耗时操作,ui线程本来就不能耗时操作 -
background
在子线程中处理事件 [一般是网络请求等耗时操作] <子线程发布事件就在子线程中处理事件,ui线程发布事件就创建新的子线程处理事件> -
async
无论在哪个线程发布事件,都将新建子线程处理事件
3.Rxjava
通讯机制
- 扩展的观察者模式
-
observable
被观察者 -
observer
观察者 -
subscribe
订阅
- 事件回调方法
-
onnext
<类似于点击> -
oncompleted
事件队列完成 -
onerror
错误
- 使用
- 创建观察者
- [重写三个回调方法]
observer
- <这个的一个抽象类
subscriber
> 用法一致 - [onstart方法在所在线程处理事件,不能更新ui,更新ui需要用doonsubscribe方法中]
- 创建被观察者
observable
- 从写call方法,内部调用
subscriber.onnext() oncompleted()
等方法,一次执行事件 - 还有
just() from()
-
subscribe
订阅事件
- 把观察者和被观察者关联起来
observable.subscribe(observer);
-
Action0() Action1()
将对象打包起来内部打包了不同的回调方法 -
scheduler
线程控制器 [指定一段代码运行在什么样的线程下]
- 默认下: 在哪一个线程调用subscriber()就在该线程产生事件,就在该线程消费事件
-
immediate()
默认情况,在当前线程运行 -
newThread()
总是创建新的线程执行代码 -
io
io操作[网络,数据库,文件读取],内部实现有一个无数量上限的线程池 -
computation
CPU计算密集型 -
mainthread
Android主线程
- 变换
- 加工整个序列,转换成不同的事件序列
-
Func1
具有返回值的包装 -
map
flatmap
Android基础
1.你常用的组件有哪些
常用组件 | 用途 |
text view | 文本显示 |
edit text | 注册框,搜索框 |
button | 登录按钮 |
float action button <悬浮按钮> | flutter中印象深刻的一个按钮,登录 |
recycle view | list view少用了,动态列表 |
switch | 白天和黑夜模式的开关 |
scroll view | 上下滑动 |
fragment | 结合view page使用布局切换 |
image view | 显示各种图片 |
check box | 订单的选择 |
web view | 新闻网页的显示 |
progress bar | 加载进度 |
spinner | 下拉消息选项 |
rating bar | 订单评价 |
search view | 搜索框 |
constraint layout | 最喜欢的一个布局 |
linear layout | 常常使用等比例均分的属性 |
grid layout | 搜索预选择的格子 |
horizontal scroll view | 横向布局 ,切换页面 |
tool bar | 首页的顶部文字显示 |
bottom navigation view | 主界面的底部导航栏 |
view | 一些分割线 |
2.Android
四大组件
- activity
- 单独的窗口
- 通过intent通讯
- 必须在
AndroidManifest.xml
配置文件中声明
- service
- 用于后台完成用户操作
- 启动,调用
startService()
- 与启动服务的组件无关
- 可以无限期运行
- 销毁服务需要调用
stopSelf() 或者 stopService()
- 绑定,调用
bindService()
- 与绑定服务的组件相关联
- 配之文件需要声明service
- content provider
- 不同程序之间的数据共享
- 使用uri标实数据集
- broadcast receiver
- 对感兴趣的外部事件进行接受并作出响应
- 可以启用一个activity或者service来响应接收到的信息
- 也可以使用notificationmanager通知用户
- 动态注册
- 生命周期随注册的activity共存亡
- 静态注册
- 生命周期独立于程序
3. 自定义view
- 自绘控件
- 继承view或者view group
- 自定义view属性
- 在res/values创建xml定义属性
- 在构造方法中获取 自定义的属性
- 重写onDraw方法
- [可选]重写onMesure方法
- 控件组合
4.约束布局
- 特点
- 百分比适配屏幕和控件
- 解决布局嵌套过多问题
- 添加动画
- 支持代码布局控件(不需要写xml)
- 和相对布局的区别
5.Serializable和Parcelable的理解和区别
序列化: 将一个对象转换成可存储和可传输的状态
- serializable
- Java自带
- 易产生大量的临时对象,容易GC
- 保证数据很好的持久性 <另外那个都东西是在内存中的啊>
- 一般还是使用这个的多,方便和持久
- 代码量少
- 使用反射,序列化过程满
- parcelable
- Android专用
- 将一个完整的对象分解,分解后的每一部分都是intent支持的基本数据类型
- 数据都在内存中,是内存的时候是很推荐的
- 效率高 <毕竟是专款专用>
6.假如手机只有10M内存,想要申请1M的内存是否一定成功
内存分配规则
算法题
1.归并排序
2. 汉诺塔
递归实现
非递归实现
3.数组反转
4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)
5.数组反转,给一个target整数,每target长度反转一次
6.最长连续子序列 O(n)
7.数组反转,给一个target整数,每target长度反转一次
8.连续最大总和
9.最长公共子序列长度
10.两个字符串是否是重排序
直接sort排序一次,比较是否相同
异或相同,取模相同
multiset集合<一个是字母排序好,一个是统计字母个数>
11.字符串轮转
两个连接字符串中查找是否含有字串
12.最近公共祖先
13.第k个丑数
双重循环,选择乘3 5 7 中最小的一个
14.到处弟k个节点
双指针走向
栈的特性