文章目录
- 学习建议
- [基础层(6 题)](#基础层(6 题))
-
- [#1 OkHttp 是什么?核心组件有哪些? 🔥](#1 OkHttp 是什么?核心组件有哪些? 🔥)
- [#2 Retrofit 的工作原理是什么? 🔥](#2 Retrofit 的工作原理是什么? 🔥)
- [#3 GET 和 POST 在 HTTP 语义上有什么区别? ⭐](#3 GET 和 POST 在 HTTP 语义上有什么区别? ⭐)
- [#4 HTTPS 基本原理?Android 中注意什么? 🔥](#4 HTTPS 基本原理?Android 中注意什么? 🔥)
- [#5 Room 三组件是什么? ⭐](#5 Room 三组件是什么? ⭐)
- [#6 RESTful API 设计在客户端如何对接? ⭐](#6 RESTful API 设计在客户端如何对接? ⭐)
- [进阶层(6 题)](#进阶层(6 题))
-
- [#7 OkHttp 拦截器链怎么工作?应用与网络拦截器区别? 🔥](#7 OkHttp 拦截器链怎么工作?应用与网络拦截器区别? 🔥)
- [#8 Retrofit 如何支持 Kotlin 协程? ⭐](#8 Retrofit 如何支持 Kotlin 协程? ⭐)
- [#9 Gson 和 Moshi/Kotlin Serialization 怎么选? ⭐](#9 Gson 和 Moshi/Kotlin Serialization 怎么选? ⭐)
- [#10 Room 数据库迁移怎么做? 🔥](#10 Room 数据库迁移怎么做? 🔥)
- [#11 Paging 3 架构是什么? ⭐](#11 Paging 3 架构是什么? ⭐)
- [#12 网络超时如何设置?重试策略? ⭐](#12 网络超时如何设置?重试策略? ⭐)
- [核心层(6 题)](#核心层(6 题))
-
- [#13 缓存策略:OkHttp 缓存与业务缓存如何配合? 🔥](#13 缓存策略:OkHttp 缓存与业务缓存如何配合? 🔥)
- [#14 离线优先(Offline-first)架构怎么实现? 🔥](#14 离线优先(Offline-first)架构怎么实现? 🔥)
- [#15 网络层安全:签名、加密、防重放? 💡](#15 网络层安全:签名、加密、防重放? 💡)
- [#16 大文件上传下载怎么做? ⭐](#16 大文件上传下载怎么做? ⭐)
- [#17 WebSocket 在 Android 中如何使用? 💡](#17 WebSocket 在 Android 中如何使用? 💡)
- [#18 数据层测试策略? 🔥](#18 数据层测试策略? 🔥)
- 面试策略速查
- 完整链路一句通
- 相关推荐
学习建议
| 目标层级 | 建议 |
|---|---|
| 初级 | 掌握基础层 6 题:OkHttp 基本用法、Retrofit 注解、GET/POST 区别、Room 三组件、HTTPS 概念 |
| 中级 | 通读全文;进阶层能讲清拦截器链、协程 suspend 适配、Room 迁移、Paging 3 架构 |
| 高级 | 核心层必答:缓存策略、网络层错误处理、离线优先、安全与证书校验;能串联「API→Repository→Room→UI」数据闭环 |
基础层(6 题)
#1 OkHttp 是什么?核心组件有哪些? 🔥
标准回答
OkHttp 是 Square 开源 HTTP 客户端,负责连接、复用、拦截、缓存与 TLS。核心:OkHttpClient(配置)、Request/Response、Interceptor 链、ConnectionPool 复用 TCP、Dispatcher 管理线程池。Retrofit 默认底层用 OkHttp。
面试官可能继续追问
-
Android 工程里 OkHttp 怎么配置?
单例
OkHttpClient注入 Hilt;设置超时、拦截器、证书;Debug 加 HttpLoggingInterceptor。 -
OkHttp 和 HttpURLConnection 区别?
OkHttp 连接池、拦截器扩展、HTTP/2 支持更好;官方与 Retrofit 生态首选。
#2 Retrofit 的工作原理是什么? 🔥
标准回答
Retrofit 用动态代理将接口方法转为 HTTP 请求:注解解析 URL、方法、参数体;Converter 序列化请求/反序列化响应(Gson/Moshi);CallAdapter 适配 suspend/Flow/Call。运行时生成实现类,无手写 HTTP 样板代码。
面试官可能继续追问
-
Android 里 Retrofit 怎么定义 API?
@GET("users/{id}") suspend fun getUser(@Path id: String): UserDto;Hilt 提供单例 Retrofit。 -
Retrofit 能传多个 BaseUrl 吗?
多 Retrofit 实例或多
@Url动态完整地址。
#3 GET 和 POST 在 HTTP 语义上有什么区别? ⭐
标准回答
GET :幂等、可缓存、参数通常在 URL,语义获取资源;POST:非幂等、提交实体,常用于创建/提交。实际 REST 还用 PUT/PATCH/DELETE;HTTPS 下两者均加密,差别在语义与缓存策略而非「安全性高低」。
面试官可能继续追问
-
Android 里搜索用 GET 还是 POST?
查询幂等用 GET;超长参数或敏感查询可 POST,但需服务端约定。
-
Retrofit
@Query和@Field区别?Query 拼 URL;Field 用于
application/x-www-form-urlencoded表单 POST。
#4 HTTPS 基本原理?Android 中注意什么? 🔥
标准回答
TLS 握手协商密钥,对称加密传数据,证书链校验服务器身份。Android 9+ 默认禁止明文 HTTP(可 networkSecurityConfig 例外);证书固定(Certificate Pinning)防中间人;勿信任所有证书;系统 CA 更新影响老设备。
面试官可能继续追问
-
Android 里怎么做证书固定?
OkHttp
CertificatePinner固定公钥哈希;注意证书轮换策略。 -
Charles 抓包原理?
用户安装代理 CA,属于中间人;生产环境应防。
#5 Room 三组件是什么? ⭐
标准回答
@Entity 表结构;@Dao 数据访问(SQL/suspend/Flow);@Database 版本与迁移入口。编译期生成 _Impl,运行时 SQLite 驱动;主线程查询默认禁止,协程/Flow 观察推荐。
面试官可能继续追问
-
Android 里 Room 实例怎么管理?
单例
Room.databaseBuilder;Hilt@Provides @Singleton;多库多实例。 -
Room 和 SQLiteOpenHelper 比?
Room 编译期校验 SQL、Lifecycle 整合;原生 Helper 更灵活但样板多。
#6 RESTful API 设计在客户端如何对接? ⭐
标准回答
资源用 URL 名词,HTTP 动词表操作;状态码表达结果(2xx 成功、4xx 客户端、5xx 服务端)。客户端映射 DTO→Domain Entity;错误体统一解析;版本通过路径或 Header;分页 page/cursor+limit。
面试官可能继续追问
-
Android 里 HTTP 错误怎么统一处理?
拦截器或
CallAdapter转Result;4xx/5xx 映射业务错误码。 -
GraphQL 和 REST 客户端差异?
GraphQL 单端点多查询;REST 多 endpoint,Retrofit 更贴 REST。
进阶层(6 题)
#7 OkHttp 拦截器链怎么工作?应用与网络拦截器区别? 🔥
标准回答
拦截器责任链:Chain.proceed(request) 向下传递,可改 request/response。应用拦截器靠近业务(日志、Header、重试);网络拦截器靠近 socket(缓存、桥接)。先加的应用拦截器先执行请求、后执行响应。
面试官可能继续追问
-
Android 里 Token 刷新拦截器怎么写?
401 时同步刷新 Token 再
proceed重放;注意死锁用单独 OkHttpClient 刷新。 -
日志拦截器放哪?
应用拦截器,避免重复读 body;body 只能读一次需
peekBody。
#8 Retrofit 如何支持 Kotlin 协程? ⭐
标准回答
接口方法声明 suspend fun,Retrofit 2.6+ 内置挂起支持,在主线程调用会自动切线程执行网络(内部 Enqueue+suspendCancellableCoroutine)。配合 viewModelScope 结构化并发;取消时取消底层 Call。
面试官可能继续追问
-
Android 里 suspend API 错误处理?
try/catch或runCatching;全局用CoroutineExceptionHandler。 -
Retrofit 返回
Flow怎么做?自定义
CallAdapter或上层flow { emit(api.get()) };官方更常见 suspend。
#9 Gson 和 Moshi/Kotlin Serialization 怎么选? ⭐
标准回答
Gson :反射解析、Kotlin null 易踩坑需适配器;Moshi :Kotlin 友好、Codegen 性能更好;Kotlin Serialization:编译期、多平台一致。新项目 Kotlin 优先 Moshi 或 KSerialization;存量 Gson 注意默认值与 null。
面试官可能继续追问
-
Android 里泛型擦除 List 怎么解析?
Gson
TypeToken;MoshiTypes.newParameterizedType。 -
Proguard 下 Gson 注意?
keep 数据类字段名;或用 Moshi codegen。
#10 Room 数据库迁移怎么做? 🔥
标准回答
版本号递增,Migration(start, end) { db.execSQL(...) } 注册到 Builder;AutoMigration(Room 2.4+)声明简单列变更。生产禁止随意 fallbackToDestructiveMigration;测试用 MigrationTestHelper 验证。
面试官可能继续追问
-
Android 里复杂迁移怎么测?
导出旧版 schema JSON,
runMigrationsAndValidate比对 schema。 -
迁移失败用户数据怎么办?
备份、降级只读、弹窗引导;开发期才 destructive。
#11 Paging 3 架构是什么? ⭐
标准回答
Pager+PagingSource 分页加载;RemoteMediator 协调网络与 Room 离线缓存;Flow<PagingData<T>> 喂给 LazyPagingItems。LoadResult 管理 prev/next key;占位符与错误重试内置。
面试官可能继续追问
-
Android 里 Compose 怎么用 Paging?
collectAsLazyPagingItems();items()渲染;loadState显示加载/错误。 -
Paging 2 和 3 区别?
Paging 3 全 Kotlin Flow、RemoteMediator 统一网络+DB;2 已维护模式。
#12 网络超时如何设置?重试策略? ⭐
标准回答
connectTimeout/readTimeout/writeTimeout/callTimeout 分层设置;读超时最常触顶。重试:幂等 GET 可指数退避;POST 谨慎自动重试。OkHttp retryOnConnectionFailure 仅连接失败;业务重试用拦截器+Idempotency-Key。
面试官可能继续追问
-
Android 里弱网怎么优化?
缩短首屏必要请求、合并接口、离线缓存、降级 UI、WorkManager 后台同步。
-
超时和 ANR 关系?
主线程
execute()同步调用会 ANR;suspend 在 IO 线程不阻塞 UI。
核心层(6 题)
#13 缓存策略:OkHttp 缓存与业务缓存如何配合? 🔥
标准回答
OkHttp Cache 按 HTTP Cache-Control/ETag 磁盘缓存;业务层 Room 存结构化离线数据。读路径:内存→Room→网络;写路径:先写 DB 再异步刷新。Cache-Control: max-age 与 stale-while-revalidate 按接口语义配置。
面试官可能继续追问
-
Android 里图片缓存和网络缓存分层?
Coil 内存+磁盘;API JSON 用 OkHttp Cache 或 Room,不混用。
-
强制刷新怎么做?
Cache-Control: no-cache或请求头pragma;Repository 参数forceRefresh。
#14 离线优先(Offline-first)架构怎么实现? 🔥
标准回答
UI 观察 Room Flow,网络仅同步;RemoteMediator 拉取写入 DB;冲突解决用版本号/时间戳/服务端权威。无网展示本地;有网后台刷新。WorkManager 定期同步;乐观更新先改本地再回滚失败。
面试官可能继续追问
-
Android 里乐观更新 UI 怎么做?
先写 Room+更新 StateFlow;请求失败回滚并提示。
-
同步冲突例子?
编辑草稿多端修改,以
updatedAt或版本向量合并。
#15 网络层安全:签名、加密、防重放? 💡
标准回答
HTTPS 传输加密;敏感字段额外 AES/RSA;请求签名(参数排序+HMAC+时间戳)防篡改;timestamp+nonce 防重放;Token 存 EncryptedSharedPreferences/DataStore;证书固定加固。密钥不进 APK 明文,用 NDK 或服务端下发。
面试官可能继续追问
-
Android 里签名校验放哪?
拦截器统一加 Header;密钥放 native 或服务器换短期 token。
-
反编译拿密钥怎么办?
提高成本非绝对安全;核心逻辑服务端校验。
#16 大文件上传下载怎么做? ⭐
标准回答
@Streaming Retrofit 返回 ResponseBody 流式写文件,勿 bytes() 一次读入;上传 RequestBody 分块或 MultipartBody;断点续传用 Range 头+本地记录偏移;进度回调用 CountingSink 包装;前台服务通知长时间下载。
面试官可能继续追问
-
Android 里下载到 MediaStore?
ContentResolver+IS_PENDING标志;Scoped Storage 合规。 -
OkHttp 取消大下载?
Call.cancel();协程取消传播到 Call。
#17 WebSocket 在 Android 中如何使用? 💡
标准回答
OkHttp WebSocket 长连接双向通信;心跳 ping/pong 保活;前台服务维持后台连接(受系统限制);重连指数退避;消息队列离线补发。与 REST 互补:实时推送用 WS,CRUD 仍 REST。
面试官可能继续追问
-
Android 里 WS 和 FCM 怎么选?
系统级推送用 FCM;低延迟双向聊天可 WS+后台限制处理。
-
Doze 对 WS 影响?
连接可能断;需重连或 FCM 唤醒。
#18 数据层测试策略? 🔥
标准回答
Room 用内存库 inMemoryDatabaseBuilder 测 DAO;Repository 用 MockWebServer 测 Retrofit 集成;Mapper 单测纯函数;PagingSource 测 load() 返回 key。不依赖真实网络;协程 runTest+TestDispatcher。
面试官可能继续追问
-
Android 里 MockWebServer 示例?
server.enqueue(MockResponse().setBody(json))断言请求路径与响应解析。 -
DAO Flow 怎么测?
turbine
test { awaitItem() }插入后断言发射。
面试策略速查
| 面试等级 | 建议掌握 |
|---|---|
| 初级 | ★★★☆☆ |
| 中级 | ★★★★☆ |
| 高级 | ★★★★★ |
必背知识(🔥)
OkHttp 组件、Retrofit 原理、HTTPS、拦截器链、Room 迁移、缓存策略、Offline-first、数据层测试
高频追问
「拦截器怎么加 Token」「suspend Retrofit 线程」「Room 迁移失败怎么办」「Paging RemoteMediator」「弱网策略」
加分项(💡)
证书固定、签名防重放、WebSocket、大文件断点续传
容易踩坑
主线程同步 OkHttp;Gson null 默认值;Room 主线程查询;POST 盲目重试;把 OkHttp 缓存当业务 DB;Token 明文存 SP
完整链路一句通
数据层一条线:Retrofit 声明 API+suspend → OkHttp 拦截器/TLS/连接池 → DTO Mapper 转 Entity → Room 持久化+Flow 观察 → Paging/RemoteMediator 协调分页与离线 → Repository 统一缓存与错误 → ViewModel StateFlow 驱动 UI;安全靠 HTTPS+存储加密+签名,测试靠 MockWebServer 与内存 Room。