### 一、Android基础
#### 1、Fragment
#### 2、Activity保存和恢复
#### 3、SharedPreferences
#### 4、[多屏幕适配](https://blog.csdn.net/carson_ho/article/details/51234308)
项目|定义|单位
---|---|---
尺寸|屏幕对角线长度|英寸(inch)
分辨率|屏幕在横向、纵向上的像素点数总和|像素(px)
像素密度|每英寸的像素点数|dpi(dots per inch)
密度无关像素|density-independent pixel,在不同像素密度的设备显示相同效果|dp/dip
独立比例像素|scale-independent pixel,用于设置字体大小|sp/sip
为了App在Android不同尺寸、不同分辨率的设备上具备相同的显示效果,就需要对App进行屏幕适配。

[今日头条屏幕适配方案](https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA)
#### 5、动画
##### 5.1 动画分类
类型|原理|特点
---|---|---
补间动画|指定View的初始状态、变化时间、方式、通过算法进行变换,形成动画效果|作用对象是View,不会真正改变View属性,效果单一
帧动画|指定每一帧的图片和播放时间,有序播放形成动画效果|效果好,但资源消耗大,繁琐
属性动画|改变View的属性,不断重绘而形成动画效果|可作用于View和对象,改变View的属性,效果丰富,可自定义
##### 5.2 [转场动画](https://www.jianshu.com/p/60c0359acc0a)
Activity跳转到另一个Activity时的动画
Android 5.0以前 - 在startActivity()或finish()后添加overridePendingTransition()来加载转场动画
Android 5.0及以后 - 调用ActivityOptionsCompat相关启动方法即可,还可以设置共享元素(用于Activity A中View和Activity B中View做平滑过渡,如微信朋友圈图片方法转场动画)
##### 5.3 ValueAnimator & ObjectAnimator
属性动画类|作用|区别
---|---|---
ValueAnimator|先改变值,然后手动赋值给对象属性来实现动画|间接对对象属性进行操作
ObjectAnimator|先改变值,然后自动赋值给对象属性来实现动画|直接对对象属性进行操作
##### 5.4 插值器 & 估值器
类型|定义|作用|应用场景
---|---|---|---
插值器(Interpolator)|辅助动画实现的接口|设置属性值从初始值过渡到结束值的变化规律。如匀速变化、加速变化、减速变化等|实现非线性运动的动画
估值器(TypeEvaluator)|辅助动画插值器的接口(属性动画特有的属性)|设置属性值从初始值过渡到结束值的变化具体数值。插值器决定属性值的变化规律,而具体变化数值则交给估值器|协助插值器实现非线性运动的动画
插值器的实现类|说明
---|---
LinearInterpolator|匀速插值器
AccelerateInterpolator|加速插值器
DecelerateInterpolator|减速插值器
AccelerateDecelerateInterpolator|落水插值器,前半段加速,后半段减速
AnticipateInterpolator|射箭插值器,后退几步再往前冲
OvershootInterpolator|回旋插值器,冲过头再归位
AnticipateOvershootInterpolator|射箭回旋插值器,后退几步再往前冲,冲过头再归位
BounceInterpolator|震荡插值器,类似皮球落地(落地后会弹起几次)
CycleInterpolator|钟摆插值器,以开始位置为中线而晃动(类似摇摆动画,开始位置与结束位置的距离就是摇摆的幅度)
属性动画的构造方法|估值器|对应的属性说明
---|---|---
ofInt|IntEvaluator|整型类型的属性
ofFloat|FloatEvaluator|大部分属性,如alpha、rotation、scaleY、translationX等
ofArgb|ArgbEvaluator|颜色,如backgroundColor、textColor等
ofObject|RectEvaluator|裁剪范围,如clipBounds
##### 5.5 [Android动画框架实现](https://blog.csdn.net/WangRain1/article/details/105809235)
补间动画Animation主要代表动画类型运行状态,Transformation 是对动画的计算和保存。

属性动画的流程可以分两部分:1.封装PropertyValueHolder对象、2.start启动动画等待刷新

#### 6、IPC、Binder机制
#### 7、[Handler源码](https://www.jianshu.com/p/ed318296f95f)
同步屏障消息就是在消息队列中插入一个屏障,在屏障之后的所有普通消息都会被挡着,不能被处理。不过异步消息却例外,屏障不会挡住异步消息,因此可以认为,屏障消息就是为了确保异步消息的优先级,设置了屏障后,只能处理其后的异步消息,同步消息会被挡住,除非撤销屏障。
配置异步消息: Message.setAsynchronous(true)
andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue
#### 8、Activity保存和恢复
#### 9、数据库
#### 10、SharedPreferences
#### 11、MVC、MVP、MVVM、MVI
### 二、Android优化
#### 1、内存优化
#### 2、应用启动流程、启动优化
#### 3、apk体积优化
#### 4、WebView优化 **==重点==**
#### 5、电量优化
#### 6、CPU优化
#### 8、模块化、组件化 **==了解大厂开源框架==**
#### 9、插件化、热更新 **==了解大厂开源框架==**
### 三、Jetpack
#### 1、Navigation **==重点==**
##### 1.1 Navigation是什么?
##### 1.2 如何使用Navigation?
##### 1.3 Navigation页面栈管理
##### 1.4 Navigation Safe Argues页面间数据传递
##### 1.5 Navigation Deeplink
#### 2、ViewModel、LiveData、LifeCycle
#### 3、DataBinding @BindingAdpter
#### 4、Compose的使用,声明式页面布局
### 四、Java
#### 1、HashMap源码分析、红黑树 **==重点==**
#### 2、多线程、线程池 **==重点==**
#### 3、面向对象设计原则、常用设计模式
#### 4、JVM内存回收机制
### 五、网络 **==重点==**
#### 1、TCP 5层网络模型
层级|作用|协议/技术|基本数据单位
---|---|---|---
物理层|确保原始的数据可在各种物理媒体上传输,可用光缆、电缆、双绞线、无线电波等介质|无|0/1光电信号
数据链路层|为网络层提供可靠的数据传输|以太网协议、ARP、MTU|帧
网络层|对子网间的数据包进行路由选择,还可以实现拥塞控制、网际互连等功能|IP、ICMP、ARP、PARP、路由|IP数据包
传输层|将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题|TCP、UDP|无
应用层|向应用程序提供服务|HTTP、FTP、Telnet、DNS、SMTP、POP3|报文
#### 2、[Http三次握手和四次挥手](https://blog.csdn.net/mini_1251861209/article/details/100533385)

client > server [SYN] client发送一个带SYN的TCP报文到server,表示client想要和server端建立连接
server > client [SYN, ACK] server接收到client的请求,返回client报文,这个报文带有SYN和ACK确认标示,访问client是否准备好
client > server [ACK] client再次响应server一个ACK确认,表示我已经准备好了
**为什么要三次握手? ** 为了防止已失效的连接请求报文段突然又传送到了服务端

client > server [FIN] TCP发送一个FIN(结束),用来关闭client到server的连接
server > client [ACK] server收到这个FIN后发回一个ACK确认标示,确认收到
server > client [FIN] server发送一个FIN到client,server关闭client的连接
client > server [ACK] client发送ACK报文确认,这样关闭完成
**为什么要四次挥手? ** 因为TCP是全双工的通信方式,即一方断开连接后,不能向另一方发送数据,但是此时另一方可以向自己发送数据,所以双方断开连接是独立的,所以需要四次。
#### 3、[Http请求头 & 响应头](https://blog.csdn.net/weixin_42408447/article/details/121396512)。
HTTP的报文头的作用是为了让client和server更加便捷的通信。
Header|解释|示例
---|---|---
Accept|指定客户端能够接收的内容类型|Accept: text/plain, text/html
Accept-Charset|客户端可以接受的字符编码集。|Accept-Charset: iso-8859-5
Accept-Encoding|指定浏览器可以支持的web服务器返回内容压缩编码类型。|Accept-Encoding: compress, gzip
Accept-Language|客户端可接受的语言|Accept-Language: en,zh
Accept-Ranges|可以请求网页实体的一个或者多个子范围字段|Accept-Ranges: bytes
Authorization|HTTP授权的授权证书|Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control|指定请求和响应遵循的缓存机制|Cache-Control: no-cache
Connection|表示是否需要持久连接。(HTTP 1.1默认进行持久连接)|Connection: close
Cookie|HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。|Cookie: $Version=1; Skin=new;
Content-Length|请求的内容长度|Content-Length: 348
Content-Type|请求的与实体对应的MIME信息|Content-Type: application/x-www-form-urlencoded
Date|请求发送的日期和时间|Date: Tue, 15 Nov 2010 08:12:31 GMT
Range|只请求实体的一部分,指定范围|Range: bytes=500-999
状态码|作用
---|---
200|OK 表示成功
303|重定向,把你重定向到其他页面
304|资源并未修改,可以直接使用本地的缓存
401|未授权,一般是token无效
403|禁止访问
404|找不到页面(页面被删除或其他)
500|服务端错误
501|服务端未实现
#### 4、[什么是心跳检测?](https://www.csdn.net/tags/NtDakgwsODkyMzMtYmxvZwO0O0OO0O0O.html)
由于移动设备的网络的复杂性,经常会出现网络断开,如果没有心跳包的检测,客户端只会在需要发送数据的时候才知道自己已经断线,会延误,甚至丢失服务器发送过来的数据。
a) 建立socket长连接
b) client通过定时向server发送心跳消息,来判断和服务器是否连接。若断开连接,需要重新手动连上server
#### 5、浏览器访问一个url网址所经历的过程是什么?
#### 6、Socket是协议吗?WebSocket是协议吗?它们的区别是什么?
Socket|WebSocket
---|---
应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口不是协议|应用层协议,建立在TCP协议之上
灵活|易用
操作底层 TCP/IP 协议族通信|在单个TCP连接上进行全双工通信
#### 7、Json解析方式有哪些?常用库、性能对比。
库名称|序列化|反序列化
---|---|---
Gson|序列化次数比较小的时候,Gson性能最好|相差不大
FastJson|和Jackson接近|相差不大
Jackson|和FastJson接近|相差不大
综合来看,FastJson的序列化和反序列化性能最强。
#### 8、XML解析方式有哪些?常用库、优缺点。
库名称|实现方式
---|---
DOM解析|通过Document类将整个xml文件一次读入内存,然后通过操作Document实例的属性实现对xml文件中元素的增删改查,会产生瞬时内存峰值
SAX解析|对xml文件采用边读边解析的方式,内存的消耗比较平稳
#### 9、http1.0、http1.1、http 2.0区别是什么?
**http1.0**
a) TCP连接不可复用,且一个TCP连接只能发送一次请求,当服务器响应后,就会关闭这次连接。这样导致每次请求都需要重新建立TCP连接(三次握手),影响发送速率,后面提供了一个非标准字段Connection字段来实现长连接,但是由于非标准字段,所以不同实现的行为可能不一致;
b) 只支持发送的http请求方式有get、post、head;
**http1.1**
a) 实现长连接,即TCP连接默认不关闭,允许被多个请求复用,不用申明Connection: keep-alive。
提供管道机制,即一个TCP连接中,允许多个请求同时发送,增加并发性,但是服务器还是根据得到请求的先后顺序去进行响应,这种机制容易造成队头阻塞。
b) 请求方式增加put、patch、options、delete等。
c) 请求头新增host字段,用来处理服务器存在多个虚拟主机的情况。
d) 提供身份认真机制,许多web站点要求用户提供一个用户名—口令对才能访问存放在其服务器中的文档,这种要求称为身份认证(authentication)。HTTP提供特殊的状态码和头部来帮助Web站点执行身份认证。
**http2.0**
a) 增加双工模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了队头堵塞的问题;
b) 服务器推送功能,当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源
c) 支持二进制帧的格式来传递报头和数据。
d) 头信息压缩机制,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
#### 10、TSL、SSL、Https

#### 11、Cookie和Session
区别类型|Cookie|Session
---|---|---
工作原理|通过检查客户端身上的“通行证”来确定客户端身份|通过检查服务器上的“客户明细表”来确认客户端身份
数据存放位置|cookie数据存放在客户端的浏览器上|session数据放在服务器上
安全程度|cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗|安全应当使用session
性能使用程度|session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能|减轻服务器性能方面,应当使用cookie
数据存储大小|单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie|session则存储与服务端,浏览器对其没有限制
### 六、Kotlin
#### 1、Kotlin相对Java的对比
简洁,消除模板代码;空类型安全;运算符重载;支持OOP, OPP两种编程方式,支持顶级函数;支持inline和inflix函数;与Java进行100%的互相调用;支持扩展属性和方法;支持协程;语法层面支持委托;支持懒加载
#### 2、委托
##### 2.1 属性委托
属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其委托给一个代理类,从而实现对该类的属性统一管理
###
val/var <属性名>: <类型> by <委托代理类>
###
##### 2.1 标准委托
类型|方法声明|作用
---|---|---
延迟属性|val name: String by lazy(initializer = initFun)|首次get name会调用initializer表达式并记录值,后续get name直接获取记录的值
可观察属性|var name: String by Delegates.observable("levine", onChange = changeFun)|用于实现数据的观察者模式,类似LiveData
属性储存在映射中|val name: String by map[注:map为Map对象]|用于解析JSON或者处理其他"动态"场景
非空属性|var name: String by Delegates.notNull<String>()|用于无法在初始化阶段就确定属性值的场合,赋值前被访问抛异常
#### 3、扩展属性、扩展函数
对一个类的属性和方法进行扩展,且不需要继承或使用 Decorator 模式。
扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。
扩展属性示例: val <T> List<T>.lastIndex: Int
扩展函数示例: fun String.extendsFun()
#### 4、Coroutine + Flow
##### 4.1 协程的概念和作用
Kotlin的协程提供一种避免阻塞且更简单可控的操作: 协程挂起(coroutine suspension),
协程将复杂异步操作放入底层库中,程序逻辑可顺序表达,以此简化异步编程,该底层库将用户代码包装为回调/订阅事件,在不同线程(甚至不同机器)调度执行。
Kotlin中用于替换线程来执行耗时操作(网络IO、文件IO、CPU/GPU密集型任务)。
##### 4.2 线程阻塞和协程挂起的区别
线程阻塞|协程挂起
---|---
代价昂贵|几乎无代价,无需上下文切换或涉及OS
通过调度CPU执行生效|可由用户控制,通过插入相关代码来生效
需要虚拟机VM/操作系统OS的支持|编译技术实现(不需要虚拟机VM/操作系统OS的支持)
##### 4.3 挂起函数
当调用[suspend修饰的函数]时会发生协程挂起:
###
suspend fun doSomething(value: Int): Unit
###
该函数称为挂起函数,调用它们可能挂起协程(如果调用结果已经可用,协程库可决定不挂起)
挂起函数能像普通函数获取参数和返回值,但只能在协程体或挂起函数中被调用。
##### 4.4 协程内部机制原理
每个挂起函数都转换为状态机,对应于挂起调用;在挂起协程前,下一状态和相关局部变量等被存储在编译器生成的类字段中;在恢复协程时,状态机从下一状态进行并恢复局部变量。
一个挂起的协程可作为保存挂起状态和局部变量的对象,对象类型是Continuation。在底层,挂起函数有一个Continuation类型的额外参数。
##### 4.5 协程的标准API
a)语言支持(如上述的挂起函数);b)Kotlin标准库中的底层核心协程API(low-level API);c)在用户代码中直接使用的高级API(high-level API)
##### 4.6 [Flow](https://zhuanlan.zhihu.com/p/114295411)
#### 5、高阶函数 Lambda
类型|定义|示例
---|---|---
函数类型|将函数的参数类型和返回值类型抽象|(Int) -> Unit
高阶函数|函数的参数或者返回值的类型是函数类型|fun test(callback: (Int) -> Unit)
Lambda|Lambda表达式就是函数的一种简写|{it-> print("123")}
将函数的参数类型和返回值类型抽象出来后,就得到了函数类型。如"(Int) -> Unit"。
用函数类型替代接口定义,用Lambda 表达式作为函数参数。作用:减少接口类的定义,代码更加简洁。
#### 6、内联函数 inline、noinline、crossinline
inline修饰的函数在在编译时将函数体嵌入到每一个调用处。内联函数可以减少对象创建,从而避免性能问题,就不怕在循环体重调用了。
修饰符|修饰位置|作用
---|---|---
inline|修饰函数|在编译时将函数体嵌入到每一个调用处。减少对象创建,不惧循环体内重调用
noinline|修饰内联函数的参数|函数参数在编译时是不会做内联处理
crossinline|修饰内联函数的参数|Lambda表达式不允许使用return,但是Lambda表达式是内联函数的参数就可以使用return。被crossinline修饰的函数类型参数将不再调用lambda表达式的return
#### 7、密封类
使用sealed声明密封类,密封类可以有子类,但是一般将子类内嵌在密封类中。
密封类是枚举的增强,除了用来区分类型,还可以给子类添加属性。
用于类型判断时,when少了对应的类型处理会有提示,而且不需要补全else。
#### 8、泛型
在Kotlin中抛弃了"? extends"和"? super"通配符,直接实现了PECS(Producer-Extends, Consumer-Super)。Kotlin引入了投射类型out T代表生产者对象,in T代表消费者者对象,来代替通配符的功能。
在Kotlin中,把只能保证读取数据时类型安全的对象叫生产者,用out T标记;把只能保证写入数据安全时类型安全的对象叫做消费者,用in T标记。
修饰符|名称|角色|Java映射|作用
---|---|---|---|---
out T|上界通配符 or 协变|生产者|? extends T|保证读取数据时类型安全
in T|下界通配符 or 逆变|消费者|? super T|保证写入数据时类型安全
Kotlin泛型实现采用运行时类型擦除的方式,即运行时泛型的类型参数信息会被擦除。过程如下:
- 首先,找到用来替换类型参数的具体类。一般是Object,如果指定了参数类型上界的话,则直接使用上界。
- 其次,把代码中的类型参数替换成具体类。同时去掉类型声明即"<>"中的内容。如ArrayList<Int>编程了ArrayList。
- 最后,根据需要生成一些桥接方法。这是由于泛型擦除后可能缺失了某些必须方法,这个时候就有编译器来动态生成这些方法。
### 七、开源框架
#### 1、Glide
#### 2、OkHttp
#### 3、Retrofit
### 八、浏览器
#### 1、针对网址导航应用做打开速度优化 [链接1](https://zhuanlan.zhihu.com/p/449965496) [链接2](https://blog.csdn.net/weixin_39950552/article/details/117554137)
a) 设置webview缓存 </br>
b) 加载动画/最后让图片下载 </br>
c) 渲染时关掉图片加载 </br>
d) 设置超时时间 </br>
e) 开启软硬件加速 </br>
f) 网页端的优化 由网页的前端工程师优化网页,或者说是和移动端一起,将网页实现增量更新,动态更新。app内置css,js文件并控制版本 </br>
#### 2、多窗口管理
a) 创建继承自FrameLayout的StackView来显示多窗口
b) 每个窗口都封装Tab中来管理,打开新窗口需要将当前窗口截图,当页面变化时也要实时更新窗口截图
c) 未将窗口缓存,限制窗口创建数量12
#### 3、[浏览器访问一个url网址所经历的过程是什么?](https://blog.csdn.net/weixin_43419753/article/details/104383972)
a) 首先,在浏览器地址栏中输入url </br>
b) 浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。 </br>
c) 在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。 </br>
d) 浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。 </br>
e) 握手成功后,浏览器向服务器发送http请求,请求数据包。 </br>
f) 服务器处理收到的请求,将数据返回至浏览器 </br>
g) 浏览器收到HTTP响应 </br>
h) 读取页面内容,浏览器渲染,解析html源码 </br>
i) 生成Dom树、解析css样式、js交互 </br>
j) 客户端和服务器交互 </br>
k) ajax查询
#### 4、某些网站使用OkHttp无法保存网页图片
使用CookieManager获取Cookie后设置Header才能正常下载
#### 5、信息流数据转换
接入多家渠道信息流API时,因为各家url和数据结构不一致,需要对各个渠道信息流进行数据转换,在Model层统一API,扩展性(符合开闭原则)
#### 6、[View事件传递](https://www.jianshu.com/p/17b62c3a8f5c)

假设activity里有一个ViewGroup,ViewGroup里有一个View,这时点击View区域,事件的传递路线是这样的:Activity.dispatchTouchEvent,ViewGroup.dispatchTouchEvent,ViewGroup.onInterceptTouchEvent,View.dispatchTouchEvent, View.onTouchEvent, 若View.onTouchEvent返回true, 后续的事件都会传递给View. </br>
若ViewGroup拦截事件, 事件就会传递给ViewGroup.onTouchEvent. 若子View不希望父容器拦截事件, 可以调用ViewGroup.requestDisallowInterceptTouchEvent(true).
#### 7、View绘制机制 [链接1](https://www.jianshu.com/p/1c26de60a8e9) [链接2](https://www.bianchengquan.com/article/25772.html)
一个页面背后是一个控件树, 根节点是ViewRootImpl.绘制界面时, 会走到ViewRootImpl.performTraversals(), 而performTraversals里会调用performMeasure(), performLayout() perfromDraw(), 这几个方法会遍历控件树上的每一个view, 来实现测量, 布局和绘制
#### 8、[滑动展开信息流动画](https://blog.csdn.net/qq_33610142/article/details/53118014)
a) 根视图使用CoordinatorLayout
b) 将滑动区域分成Header搜索区、搜索天气网址导航区(NestedScrollView)、信息流区(TabLayout+ViewPager)
c) 给三个滑动区域自定义Behavior实现view之间的联动
#### 9、频道列表
ItemDragHelperCallback实现”我的频道“拖拽完成添加删除
#### 10、网页视频
全屏播放 </br>
点击全屏按钮时,WebChromeClient.onShowCustomView()会被调用,需要执行以下操作: </br>
1 隐藏webview </br>
2 将视频view添加到当前页面,并显示出来 </br>
3 设置屏幕方向为横屏 </br>
自动播放 </br>
###
videoAutoPlayJS = AssetsFile.getFormAssets(mContext, "auto_play.js");
view.loadUrl(videoAutoPlayJS);
###
"auto_play.js"里判断到若当前使用的移动网络就会弹出窗口让用户确认, 不是移动网络就自动播放
#### 11、JS和Android之间的调用
###
mwebview.getSettings().setJavaScriptEnabled(true); 设置是否允许加载js
mMainView.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj"); 注册java对象给js调用
mMainView.setWebViewClient(mWebViewClient); 这里可以接收到页面开始加载, 加载结束的回调
mMainView.setWebChromeClient(mWebChromeClient); 这里可以接收到js弹窗回调, 例如在js弹出允许定位提示窗等
###
JSBridge </br>
安全漏洞(Android4.2以上,允许被JavaScript调用的方法必须以@JavascriptInterface进行注解声明,从而避免漏洞攻击)
#### 12、如果有问到怎么实现书签同步时,可以讲一下思路
### 九、应用商店
#### 1、应用安装
静默安装 -- 需要系统签名和系统权限(INSTALL_PACKAGES) </br>
安装状态监听 - 监听系统广播(ACTION_PACKAGE_ADDED、ACTION_PACKAGE_REMOVED)
#### 2、[多线程](http://concurrent.redspider.group/article/01/1.html)
##### 2.1 线程和进程
通常进程就是一个运行得应用程序,而线程是应用程序运行时的任务执行者。进程中包含了多个可以同时运行的线程,如Android中一个应用程序可以同时包含UI线程和工作线程

##### 2.2 线程安全
多个线程访问同一个资源时,若A线程对该资源进行写操作中途,同时B线程对这个资源进行了读写操作,因此引发数据问题。
**a) synchronized** -- 多个线程同时访问被synchronized修饰的方法,仅有一个线程可以访问,其它线程只能等待。当该线程线程访问完毕后,下一个线程才可以访问 </br>
**b) ReentrantLock** -- 重入锁。调用lock()锁定同步,调用unlock()解锁同步。 </br>
**c) AtomicInteger** -- 适用场景:多个线程访问同一个整型数值;自增/自减;作为流水值使用;线程安全,使用原子锁 </br>
**d) volatile** -- 保证变量的内存可见性;禁止指令排序 </br>
**e) notify & notifyAll** -- notify是只唤醒一个等待的线程,noftifyALl是唤醒所有等待的线程 </br>
##### 2.3 [线程池](https://www.liangzl.com/ce/interview.html)

种类|核心线程数|非核心线程数|任务队列|适用场景
---|---|---|---|---
CachedThreadPool|0|Integer.max_value|SynchronousQueue|适合任务量大但耗时少的场景
FixedThreadPool|用户指定|0|LinkedBlockingQueue|适合任务量比较固定但耗时长的场景
SecudleThreadPool|用户指定|用户指定|DelayedWorkQueue|支持定时及周期性任务执行
SingleThreadPool|1|0|LinkedBlockingQueue|适用于多个任务顺序执行的场景
**应用商店中适用 "FixedThreadPool" 的方式来创建线程池,实现多个app的下载。**
#### 3、[网络优化](https://www.jianshu.com/p/6270ca473c11)
##### 3.1 工具
a) Network Monitor -- Android Studio自带的Network Monitor简单直观,可以看出时间段之内的网络请求数量及访问速率 </br>
b) 抓包工具 -- 使用Charles、Fiddler等抓包工具同样可以实现Network Monitor的功能,而且更加强大 </br>
c) Stetho -- Facebook出品的一个Android应用的调试工具。无需Root即可通过Chrome,在Chrome Developer Tools中可视化查看应用布局,网络请求,sqlite,preference等。同样集成了Stetho之后也可以很方便的查看网络请求的各种情况 </br>
##### 3.2 优化
可以从三个方面进行网络优化:**1. 提高访问速度;2. 提高访问成功率;3. 节省流量**
**a) Gzip编码** -- HTTP传输数据使用Gzip压缩编码,减少流量消耗和传输时间 </br>
**b) 请求打包** -- 合并网络请求,减少请求次数。将打点信息缓存在本地,然后根据策略统一接口上传 </br>
**c) 网络缓存** -- 对服务端返回的数据进行缓存,设定有效期。有效期内不走网络请求,减少流量消耗 </br>
**d) 网络状态** -- 根据不同网络状态进行业务处理,如WiFi网络下优先进行打点和数据预获取。弱网状态下减少网络请求频次。网络状态可以由TelephonyManager.getNetworkType()方法获取 </br>
**e) 断点下载/上传** -- 使用断点下载或断点上传,不浪费用户之前消耗过的流量 </br>
**f) 推送** -- 获取实时信息不客户端轮询,而使用服务器推送 </br>
**g) 图片优化** -- 加载网络图片时,尽量使用webp格式图片。还可以根据实际尺寸来获取图片(需要服务器支持多尺寸图片) </br>
**h) IP直连** -- DNS解析的失败率占联网失败中很大一种,而且首次域名解析一般需要几百毫秒。针对此,不用域名,才用IP直连省去 DNS 解析过程,节省时间。 </br>
**i) HttpDNS** -- 基于Http协议的域名解析,替代了基于DNS协议向运营商Local DNS发起解析请求的传统方式,可以避免Local DNS造成的域名劫持和跨网访问问题,解决域名解析异常带来的困扰 </br>
**j) 协议层优化** -- Http协议有多个版本:0.9、1.0、1.1、2等。Http1.1版本引入了“持久连接”,多个请求被复用,无需重建TCP连接;Http2引入了“多工”,包含头信息压缩、服务器推送等特性 </br>
**k) 增量更新** -- 数据更新采用增量,而不是全量,仅将变化的数据返回,客户端进行合并
##### 3.3 弱网模拟工具
a) 使用抓包工具进行模拟,或者使用wifi精灵进行网络限速 </br>
b) Facebook的开源项目augmented-traffic-control可以模拟不同的网络环境,针对带宽、时延抖动、丢包率、错包率、包重排序率等方面
#### 4、[断点下载](https://www.jianshu.com/p/e25dd4f88d08)
**a) 添加Header** -- "Range:bytes=start-end",下载范围,从开始到结束的位置 </br>
**b) RandomAccessFile** -- 使用RandomAccessFile类来实现文件写入 </br>
**c) 数据库缓存** -- 将文件下载状态[已下载size、文件位置等信息]写入SQLite数据库,如果出现下载中断后,如果要继续下载可以从数据库恢复状态
#### 5、全局异常处理
**a) 创建CrashHandler** -- "public class CrashHandler implements Thread.UncaughtExceptionHandler",重写其uncaughtException(Thread t, Throwable e)方法 </br>
**b) 修改Application** -- 在Application的onCreate方法中添加"Thread.setDefaultUncaughtExceptionHandler(CrashHandler.getInstance(this))"
#### 6、[ASpectJ非侵入式集成数据埋点功能](https://blog.csdn.net/u011897062/article/details/108213776)
##### 6.1 AOP
面向切面编程。它提倡的是针对同一类问题的统一处理,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
##### 6.2 适用场景
判定登录状态、日志打点、动态请求权限、多线程的切换
##### 6.3 [ASpectJ](https://developer.aliyun.com/article/864902)
AspectJ实际上是对AOP编程思想的一个实践,开发了一套语言来支持AOP。它是一种几乎和Java完全一样的语言,除了使用AspectJ特殊的语言外,AspectJ还支持原生的Java,只要加上对应的AspectJ注解就好。
**a) Aspect 切面** -- 切面是切入点和通知的集合 </br>
**b) PointCut 切入点** -- 切入点是指那些通过使用一些特定的表达式过滤出来的想要切入Advice的连接点 </br>
**c) Advice 通知** -- 通知是向切点中注入的代码实现方法 </br>
**d) Joint Point 连接点** -- 所有的目标方法都是连接点 </br>
**e) Weaving 编织** -- 主要是在编译期使用AJC将切面的代码注入到目标中, 并生成出代码混合过的.class的过程
#### 7、ReyclerView相关
##### 7.1 ReyclerView四级缓存

##### 7.2 ReyclerView和ListView区别
**a)布局区别** -- RecyclerView支持列表、表格、瀑布流布局,ListView只支持竖向列表 </br>
**b)缓存区别** -- RecyclerView有四级缓存,ListView只有两级缓存 </br>
**c)局部刷新** -- RecyclerView支持列表局部刷新,ListView不支持
##### 7.3 RecyclerView性能优化
a) 数据处理与视图加载分离 </br>
b) Item布局优化 </br>
c) 设置RecyclerView.addOnScrollListener()来在滑动过程中停止加载的操作
#### 7.4 RecyclerView滑动引发搜索栏背景渐变动画
监听RecylerView滑动,在ReyclerView显示第一个时设置搜索栏透明度为0;当RecylerView滑动时,使用getScrollY()来做搜索栏透明度的变化。
#### 7.4 ItemDecoration
**a) onDraw** -- 通过Canvas绘制内容,需要注意的是onDraw绘制会先于Item绘制。如果在onDraw中绘制的内容在Item边界内,就会被Item遮挡住,所以onDraw()一般会和 getItemOffsets结合一起使用,即在矩形框与Item的间隔区域内绘制内容 </br>
**b) onDrawOver** -- 通过Canvas绘制内容,但与onDraw的区别是:onDrawOver绘制是后于 onDraw的,所以绘制内容是不会被 Item 所遮挡的,反而Item会被onDrawOver 绘制的内容所遮挡 </br>
**c) getItemOffsets** -- RecyclerView的Item 外面是包裹着一个矩形框,该方法就是用来设置矩形框与Item之间的间隔的
#### 8、[Glide缓存机制在应用商店的使用,如何使用](https://blog.csdn.net/weixin_42600398/article/details/120697944)

Glide的磁盘缓存使用的是 LRU 算法,对应的实现工具为 DiskLruCache。

#### 9、ViewPager设置
**a) 预加载页面** -- 应用商店中offscreenPageLimit预加载页默认等于1 </br>
**b) 页面保持** -- 应用商店中设置setOffscreenPageLimit(5),使ViewPager在示5个Fragment之间切换时不会销毁Fragment,保证页面状态不被重置 </br>
**c) 转场动画** -- 创建类实现ViewPager.PageTransformer,然后给ViewPager设置setPageTransformer
### 十 Mobile App
#### 1、MQTT
#### 2、将异步回调转换成Flow
#### 3、多页面监听同一数据(MutableSharedFlow),替换EventBus
#### 4、MVVM