客户端面试八股文-Android第三方库
okhttp拦截器okhttp拦截器分为两大类应用拦截器网络拦截器以及内部封装的系统拦截器通过责任链模式串联执行执行链路顺序1、自定义应用拦截器最先执行最早拿到原始请求最晚拿到响应2、RetryAndFollowUpInterceptor重试重定向拦截器处理IO异常重试301/302重定向401鉴权等限制最大重定向次数默认20次3、BridgeInterceptor桥拦截器补全请求头解析响应编码上层业务与底层网络的桥梁自动补全Content-TypeUser-AgentAccept-Encoding响应自动解压封装字符编码4、CacheInterceptor缓存拦截器处理本地缓存逻辑5、ConnectInterceptor 建立TCP/SSL链接从连接池RealConnectionPool获取可用TCP链接无空闲链接则新建Socket完成SSL握手6、自定义网络拦截器 只走真实网络请求缓存命中不走这里7、CallServerInterceptor 真正发请求责任链RealInterceptorChain原理核心1、每一层拦截器调用chain.proceed()才会放行给下一个拦截器2、执行是递归链式先从上倒下处理请求全部放行后再从下到上回传响应3、每一层都可以修改请求直接返回自定义Response拿到上层返回的响应再加工Retrofit 动态代理Retrofit 是基于 OkHttp 封装的 RESTful HTTP 请求框架由 Square 公司开源它本身不直接做网络 IO只是一套请求声明 解析转换的上层封装底层完全依赖 OkHttp 完成真实网络请求。Android优化方面内存优化内存泄漏优化1、Handler使用静态内部类弱引用WeakReference包裹activity2、所有注册类广播定位传感器onDestroy统一unregister3、单例统一传入getApplicationContext 禁止传Activity4、Webview独立进程销毁时webview.destroy 移除父布局5、页面退出清空集合置空webview取消网络请求call.cancel()6、异步线程不要持有页面引用避免页面关闭线程仍在运行图片内存优化1、大图压缩2、图片格式选择webppng3、图片缓存三级缓存内存LRU 磁盘缓存内存缓存设置合理阈值4、Glide/Coil自动复用Bitmap池禁止自己new Bitmap5、大图下载加Streaming分段式读取不一次性加载进内存其他内存优化避免内存抖动减少匿名临时对象字符串拼接用StringBuider布局复用 includemerge减少view对象数量大数组按需创建用完及时置空使用LeakCanary检测泄漏Profiler查看堆内存对象实例数量冷启动优化Application瘦身1、不要再主线程做初始化2、延迟加载库3、子线程初始化SDK禁止阻塞主线程4、区分渠道调试环境Debug只加载必要组件页面布局优化首页布局扁平化减少层级移除冗余嵌套延迟加载非关键UI避免onCreateonResume做大量耗时计算业务逻辑延迟首页网络请求延迟到页面渲染完成预加载缓存本地数据启动先展示缓存再刷新网络数据库操作放子线程卡顿优化主线程耗时操作转移至子线程网络请求数据库读写文件IO大图解码JSON解析等布局绘制优化减少布局层级使用ConstraintLayout代替LinearLayout多层嵌套减少过度绘制减少自定义View onDraw内复杂逻辑循环频繁new对象图片避免clipPath模糊渲染等昂贵渲染操作内存抖动复用对象池列表滑动卡顿1、复用ViewHolder禁止在onBindViewHolder创建对象2、图片加载异步滑动时暂停加载3、减少Item布局层级4、使用局部刷新5、滑动时不做耗时操作包体积优化资源压缩图片png转webp大图压缩删除无用图片矢量图替代多张分辨率png无用资源清理开启shrinkResource自动删除未引用资源音视频压缩代码优化1、开启混淆2、第三方SDK裁剪按需引入模块3、移除重复依赖统一版本implementation改为api按需调整4、业务废弃类工具类及时删除原生so库转化只保留目标ABI架构压缩so去除调试符号拆分功能so动态下发打包配置开启资源压缩代码混淆动态功能模块非核心业务分包按需下载弱网优化请求层okhttp优化1、调整超时时间弱网延长2、失败重试机制3、请求防抖重复请求合并短时间多次相同接口只发一次4、拦截器统一捕获IO异常超时异常友好提示用户缓存策略1、本地持久缓存接口数据弱网优先展示缓存2、区分实时接口和非实时接口非实时开启HTTP缓存3、数据库缓存首页列表基础配置业务层策略1、大文件断点续传分块上传/下载2、表单数据本地持久化弱网下离线缓存网络恢复自动重发3、图片分步加载先缩略图4、网络状态监听无网/弱网弹窗提示流量节省弱网下关闭预加载轮询长连接心跳拉长间隔图片自动降质kotlin语法糖kotlin协程 withContextlaunchasync await dispatcherskotlin顶级函数扩展函数 koltin内联函数kotlin by lazy 单例顶级函数不包裹在class/object/interface内部直接写在kt文件最外层的函数属于文件级全局函数原理是Kotlin编译后会生成文件名kt的静态工具类函数全部变成public static方法扩展函数作用在不修改原有类源码不继承的前提下给已有类新增方法底层不是真正给类新增成员方法编译后是静态工具方法接受对象作为第一个参数内联函数 inline需要的原因:普通高阶函数lambda会生成匿名内部类对象 频繁调用造成内存抖动gc频繁inline会在编译时把函数体lambda代码直接拷贝到调用处不生成额外class不创建对象消除开销1、inline整个函数内联lambda直接复制到调用点支持lambda内return非局部返回直接退出外层函数2、noinline多个lambda参数时不想某一个被内联加noinline该lambda保留对象引用可当做参数传递3、crossinline禁止lambda内部使用非局部return只能returnlabel多用于lambda会被嵌套运行如Runnable协程调度缺点代码膨胀多处调用会复制大量代码方法体超大的不建议inlineby lazy 延迟初始化 Kotlin 四种单例by lazy延迟初始化懒加载声明时不执行第一次使用才创建只初始化一次后续直接取缓存值只能修饰val不能修饰var默认同步锁多线程安全kotlin object class data class伴生对象data class 数据类专门用来承载数据编译期自动生成样板代码约束1、主构造必须至少一个参数2、参数建议用val3、不能继承其他类可实现接口伴生对象 companion object写在普通类内部的companion object一个类只有一个伴生对象1、基础作用替代 java static静态方法/静态变量kotlin没有static关键词全靠伴生对象实现2、底层原理companion object会生成一个静态内部类并在外部类持有 public static final Companion INSTANCERecyclerView缓存详解目标减少inflate()创建view开销减少onBindViewHolder()数据绑定开销提升滑动流畅度缓存优先级 Scrap --- Cache --- ViewCacheExtension --- RecycledViewPool概念1、ViewHolder承载View实例 viewType position 绑定的数据状态2、Scrap / Cache 保存完整绑定好的ViewHolder 持有效数据3、RecycledViewPool 只缓存裸View数据全部清空取出必须重新bind4、触发回收列表滚动Item滑出屏幕LayoutManager负责回收复用调度一、缓存拆解1、Scrap临时一级缓存Scrap Heap存储位置RecyclerView.mAttachedScrap容量无固定上限存放当前屏幕上正在布局的Item生命周期仅在layout()布局流程内临时生效布局完成就清空放入布局开始前把屏幕上所有可见的ViewHolder先丢进Scrap缓存取出布局过程中优先从Scrap拿ViewHolder复用取出后不需要重新inflate不需要重新onBindViewHolder使用场景调用notifyItemChanged局部刷新滚动重新布局时屏幕上还在显示的条目直接复用Scrap中的ViewHolder避免重复绑定特点临时缓存不能跨布局周期复用布局结束时所有Scrap条目会被转移到Cache或者Pool2、Cache二级缓存mCachedViews容量默认2可以手动设置存放刚滑出屏幕相邻的少量ViewHolder核心特性从cache取出无需inflate无需执行onBindViewHolder数据保留这是滑动体验最优的缓存淘汰规则Cache是先进先出队列缓存满了后最先进入的Cache的ViewHolder会被移出Cache进入RecycledViewPoolCache区分ViewType不同类型互不干扰Cache里的ViewHolder仍然记录原有Position适合邻近来回滑动的场景3、ViewCacheExtension三级扩展缓存系统默认空实现开发者业务实现4、RecycledViewPool四级缓存回收池关键区分Cache保存带数据的ViewHolderRecycledViewPool只缓存View视图清空原有绑定数据1、按viewType分组缓存不同viewType条目分开存放2、默认每个viewType最多缓存5个ViewHolder可手动调整容量3、取出规则拿到view实例必须重新执行onBindViewHolder二、复用查找流程当 RecyclerView 需要一个新 Item 视图时执行顺序先查 AttachedScrap布局阶段优先从 Scrap 寻找匹配 viewType、position 的 VH找到直接复用不 bind。找不到 → 查询mCachedViewsCache 缓存匹配 viewType找到直接复用不 bind。找不到 → 查询ViewCacheExtension自定义缓存找不到 → 查询RecycledViewPool找到 ViewHolder需要调用onBindViewHolder绑定数据Pool 也没有 →LayoutInflater.inflate 创建新 View 新建 ViewHolder三、回收流程LayoutManager 滚动时回收滑出屏幕的 ViewHolder先判断能不能放进mCachedViewsCache 没满 → 存入 CacheCache 已满 → 将队列头部旧 VH 踢出丢进 RecycledViewPool进入 Pool 前会清空 ViewHolder 内部的数据、位置信息注意Scrap 里的条目不会直接进入 Pool布局结束后优先尝试进入 Cache。