Android 面试题大全

Android 面试题大全(进阶补充版)

本文档为《Android面试题大全》的补充篇,覆盖 **Gradle 工程化、NDK/JNI、音视频、图形渲染、热修复/插件化、安全逆向、跨平台、Framework 深入、Java 并发进阶、大厂场景设计题、HR 面** 等第一份未深入的方向。

目录

  1. Java 并发编程进阶(#一java-并发编程进阶)

  2. JVM 深入与调优(#二jvm-深入与调优)

  3. Kotlin 进阶(#三kotlin-进阶)

  4. Gradle 构建与工程化(#四gradle-构建与工程化)

  5. NDK / JNI / C++ 基础(#五ndk--jni--c-基础)

  6. 音视频开发(#六音视频开发)

  7. 图形渲染系统(#七图形渲染系统)

  8. 热修复 / 插件化 / ClassLoader(#八热修复--插件化--classloader)

  9. 安全与逆向(#九安全与逆向)

  10. 动画体系(#十动画体系)

  11. WebView 深入(#十一webview-深入)

  12. 跨平台技术(#十二跨平台技术)

  13. Framework 深入(#十三framework-深入)

  14. 蓝牙 / 传感器 / 定位(#十四蓝牙--传感器--定位)

  15. 测试与 CI/CD(#十五测试与-ci-cd)

  16. 操作系统与网络进阶(#十六操作系统与网络进阶)

  17. Compose 进阶(#十七compose-进阶)

  18. 大厂场景设计题(#十八大厂场景设计题)

  19. HR 面与软技能(#十九hr-面与软技能)

一、Java 并发编程进阶

  1. 什么是 AQS(AbstractQueuedSynchronizer)?
  • JUC 的核心框架,用一个 volatile int state + CLH 双向队列实现同步。

  • 获取失败封装为 Node 入队,park 阻塞;释放时 unpark 唤醒后继节点。

  • ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock 都基于 AQS。

  • 模板方法模式:子类只需实现 tryAcquire/tryRelease。

  1. CAS 原理与问题?
  • Compare And Swap,CPU 原子指令(cmpxchg),比较内存值与预期值,相同则更新。

  • Java 通过 Unsafe.compareAndSwapInt 实现,AtomicXXX 全家桶基础。

  • 三大问题:

  • ABA 问题 → AtomicStampedReference(版本号)。

  • 自旋开销 → LongAdder 分段累加。

  • 只能保证单个变量 → AtomicReference 包对象。

  1. ThreadLocal 原理与内存泄漏?
  • 每个 Thread 持有 ThreadLocalMap,key 是 ThreadLocal 弱引用,value 是强引用。

  • ThreadLocal 被回收后 key 变 null,但 value 仍被 Entry 持有 → 泄漏。

  • 解决:用完必须 remove()(finally 中)。

  • Android 中的场景:Looper 的 ThreadLocal 存储,Handler 拿当前线程 Looper。

  1. ReentrantReadWriteLock 如何实现读写锁?
  • AQS 的 state 拆成两部分:高 16 位读锁计数,低 16 位写锁重入计数。

  • 读锁共享(多个读线程),写锁独占。

  • 锁降级:写锁 → 读锁可以(写后读);读锁 → 写锁不可以。

  • 适用:读多写少,如缓存。

  1. CountDownLatch、CyclicBarrier、Semaphore 区别?

| 工具 | 作用 | 可复用 |

|------|------|--------|

| CountDownLatch | 等待 N 个任务完成 | 否 |

| CyclicBarrier | N 个线程互相等待到同一屏障 | 是(reset) |

| Semaphore | 限制同时访问的线程数 | 是 |

  1. ConcurrentHashMap 1.8 的 put 流程?

  2. 计算 hash(spread 抑制碰撞)。

  3. table 为空则 initTable(CAS + sizeCtl 控制)。

  4. 桶为空 → CAS 放入。

  5. hash == MOVED(-1)→ helpTransfer 协助扩容。

  6. 否则 synchronized 锁桶头节点,链表尾插或红黑树插入。

  7. binCount 判断是否 treeify。

  8. addCount 统计(CounterCell 分段计数)。

7. 线程死锁的四个必要条件与排查?

  • 条件:互斥、持有并等待、不可剥夺、循环等待。

  • 排查:`jstack <pid>` 看 "Found one Java-level deadlock";Android 可用 `debug.dumpHprofData` + MAT。

  • 预防:固定加锁顺序、tryLock 超时、缩小锁粒度。

8. ForkJoinPool 与 Work-Stealing 算法?

  • 每个线程有独立双端队列,自己从头取任务,空闲线程从别人队尾偷任务。

  • 减少锁竞争,适合分治任务(并行流、CompletableFuture 底层)。

9. CompletableFuture 常用 API?

```java

CompletableFuture.supplyAsync(() -> fetch()) // 异步执行

.thenApply(d -> d.transform()) // 转换

.thenCombine(other, (a, b) -> merge(a, b)) // 合并两个

.exceptionally(e -> fallback()) // 异常兜底

.allOf(f1, f2, f3) // 全部完成

```

  • 适合编排多个异步任务(并行请求多个接口聚合)。

10. happens-before 规则有哪些?

  • 程序顺序规则、监视器锁规则、volatile 规则、线程 start/join 规则、传递性。

  • 是 JMM 判断数据是否存在竞争、是否可见的依据。


二、JVM 深入与调优

1. 类加载的完整过程?

加载(生成 Class 对象)→ 验证 → 准备(静态变量分配默认值)→ 解析(符号引用转直接引用)→ 初始化(执行 `<clinit>`,静态变量赋真实值)。

2. 对象的创建过程?

  1. 类加载检查。

  2. 分配内存(指针碰撞 / 空闲列表)。

  3. 初始化零值。

  4. 设置对象头(MarkWord、类型指针)。

  5. 执行 `<init>` 构造。

3. 对象的内存布局?

  • 对象头:MarkWord(哈希码、GC 分代年龄、锁标志)+ 类型指针 + 数组长度(数组才有)。

  • 实例数据:字段(long/double 优先对齐)。

  • 对齐填充:补齐 8 字节倍数。

4. Android 的 ART 与标准 JVM 的差异?

  • ART 无永久代,dex 走自己的结构(DexFile)。

  • AOT/JIT/PGO 混合编译,dex2oat 生成 oat/vdex。

  • GC 以并发复制收集器(Concurrent Copying, CC)为主,不分永久代、代际弱化(年轻代用 bump-pointer)。

  • GC Root 包含 JNI 全局引用、正在加载的类等 Android 特有项。

5. 常见 GC 收集器对比?

| 收集器 | 代 | 算法 | 特点 |

|--------|-----|------|------|

| Serial | 新生代 | 复制 | 单线程,客户端 |

| Parallel Scavenge | 新生代 | 复制 | 吞吐量优先 |

| CMS | 老年代 | 标记清除 | 并发低停顿,已废弃 |

| G1 | 全堆 | Region 化 | 可预测停顿,>4G 堆 |

| ZGC | 全堆 | Region/染色指针 | 停顿 <1ms |

6. 内存抖动(Memory Churn)是什么?怎么排查?

  • 频繁创建短生命周期对象 → 频繁触发 Young GC → GC 时暂停所有线程(STW)→ 卡顿。

  • 典型场景:onDraw 中 new Paint/Path、循环中拼接字符串。

  • 排查:Android Profiler 看内存锯齿;Memory Profiler 记录分配栈定位。

7. 如何分析 hprof 文件?

  1. Profiler / `am dumpheap` 导出。

  2. MAT 打开 → Dominator Tree(支配树)看最大对象。

  3. Path to GC Roots(排除弱/软引用)找持有链。

  4. LeakCanary 自动化日常监控。

8. 强软弱虚引用在 Android 中的实际应用?

  • 软引用:早期图片缓存(现已用 LruCache)。

  • 弱引用:Handler 修复、Glide 的 ActiveResources(正在使用的资源弱引用池)。

  • 虚引用:NativeAllocationRegistry 跟踪 Native 内存释放(Bitmap 像素数据)。


三、Kotlin 进阶

1. inline、noinline、crossinline 的区别?

  • inline:内联函数,lambda 直接复制到调用处,减少对象创建,是 reified 的前提。

  • noinline:被 inline 函数中不需要内联的 lambda 参数。

  • crossinline:禁止 lambda 中非局部返回(因为内联后 return 语义变化)。

2. reified 关键字的作用?

```kotlin

inline fun <reified T : Activity> Context.startActivity() {

startActivity(Intent(this, T::class.java))

}

```

  • 内联后泛型类型在编译期真实存在,可 `T::class.java`,避免传 Class 参数。

  • Gson、Retrofit 的扩展封装常用。

3. 协程取消的原理?

  • cancel 只是设置状态位,挂起点(suspend 函数)检查 isActive 抛 CancellationException。

  • CPU 密集循环需手动 `ensureActive()` 或 `yield()` 检查。

  • finally 中清理资源,若需挂起操作用 `withContext(NonCancellable)`。

4. 协程异常处理机制?

  • launch:异常立即向上传播,由 CoroutineExceptionHandler 捕获。

  • async:异常存在 Deferred,直到 await 才抛出;根作用域中 async 也会立即取消兄弟。

  • SupervisorJob:子协程异常不波及其他子(supervisorScope)。

  • 结构化并发:异常会导致父 Job 取消所有子。

5. Flow 与 LiveData 如何选择?

| 对比 | LiveData | Flow |

|------|----------|------|

| 线程 | 主线程 setValue | 任意,可切线程 |

| 操作符 | 无 | map/filter/combine 等 |

| 背压 | 无 | buffer/conflate/collectLatest |

| 生命周期 | 自感知 | repeatOnLifecycle 辅助 |

| 冷热 | 热 | 冷(StateFlow/SharedFlow 热) |

新项目推荐:UI 层 StateFlow + collectAsStateWithLifecycle。

6. StateFlow 与 SharedFlow 区别?

  • StateFlow:必须有初始值、值去重(conflate+distinctUntilChanged)、永远有最新值,适合 UI 状态。

  • SharedFlow:可配置 replay/extraBufferCapacity、无初始值、支持事件(用 replay=0),适合一次性事件。

  • 事件流不要用 StateFlow(会有丢失和粘性问题)。

7. Kotlin 密封接口(sealed interface)与密封类区别?

  • interface 支持一个类同时实现多个密封接口,类只能单继承。

  • 1.6 后密封子类只需在同模块即可(跨文件)。

8. by 委托的原理?

  • 属性委托:`by lazy` 编译为 Lazy 对象 + getValue 调用。

  • 类委托:`class A(b: B) : B by b`,编译器生成转发方法。

  • 自定义委托需实现 `getValue/setValue`(ReadWriteProperty)。

9. Kotlin 与 Java 混用的坑?

  • 平台类型(Platform Type):Java 返回值可空性未知,需显式检查。

  • @JvmOverloads 生成重载,@JvmStatic 生成静态,@JvmField 暴露字段。

  • 协程 suspend 无法直接被 Java 调用(需 Continuation 参数)。

  • Kotlin 属性 x 编译为 getX/setX,is 开头特殊。

10. Kotlin 编译产物与 Java 有什么不同?

  • 支持 null 检查(Intrinsics.checkNotNull)插入。

  • lambda 编译为 Function 对象(非内联时)。

  • 协程经 CPS 变换, suspend 状态存于 Continuation。

  • 默认参数生成合成方法;data class 生成 copy/componentN。


四、Gradle 构建与工程化

1. Gradle 构建生命周期?

  1. Initialization:执行 settings.gradle,确定参与构建的模块,创建 Project 对象。

  2. Configuration:执行各模块 build.gradle,生成 Task DAG。

  3. Execution:按依赖顺序执行 Task。

2. buildSrc 与 Version Catalog 的区别?

  • buildSrc:单独模块,代码写依赖版本(Groovy/Kotlin),参与编译、影响构建缓存。

  • Version Catalog(libs.versions.toml):Gradle 7.4+ 官方依赖版本管理,配置即用、不影响构建速度、IDE 支持好,推荐。

3. 常见提升构建速度的手段?

  • org.gradle.parallel=true(模块并行)。

  • org.gradle.caching=true(构建缓存)。

  • kapt 改 KSP(快 2 倍以上)。

  • 模块化拆分 + 按需构建(-am 只构建依赖)。

  • Gradle Remote Build Cache / CI 缓存。

  • R8 优化、禁用不必要的 Transform。

4. AGP 的 Transform API 与 ASM?

  • Transform:class 转 dex 前的插桩入口(已废弃,新版用 AsmClassVisitorFactory / Instrumentation API)。

  • 场景:无埋点(自动插桩)、性能监控、方法耗时统计。

  • ASM:Core API(事件流)与 Tree API(树形结构),常用于字节码注入。

5. ProGuard / R8 的作用与常用规则?

  • 作用:压缩(shrink)、优化(optimize)、混淆(obfuscate)、预校验。

  • R8 是 AGP 默认,替换 ProGuard 并做 dex 合并。

  • 常用规则:

```

-keep class com.x.Model { *; } // 保留类与成员

-keepclassmembers class * { @Keep *; } // 配合 @Keep 注解

-dontwarn okhttp3.** // 忽略警告

```

  • 反射、JNI、序列化、枚举 values 需 keep。

6. APK 签名 v1/v2/v3/v4 的区别?

| 方案 | 校验粒度 | 版本 |

|------|----------|------|

| v1 (JAR) | 单个文件条目 | 全部 |

| v2 (APK) | 整个 APK | 7.0+ |

| v3 | v2 + 密钥轮换证明 | 9.0+ |

| v4 | 增量安装 fs-verity | 11+ |

  • v2 解决 v1 的 ZIP 条目篡改(META-INF 不参与校验)问题。

7. 什么是 AAB(Android App Bundle)?

  • Google Play 上传格式,按需分发 split APK(base + config)。

  • Play 自动按设备 ABI/密度/语言生成最小 APK。

  • Feature Delivery:on-demand / conditional 模块动态下发。

  • Play Asset Delivery 适合游戏大资源。

8. 自定义 Gradle 插件的步骤?

  1. 实现 `Plugin<Project>` 接口的 apply 方法。

  2. 定义 Extension(DSL 参数)与 Task。

  3. 发布方式:buildSrc / 独立模块(maven-publish)/ composite build。

9. Maven 仓库与依赖冲突处理?

  • 传递依赖冲突:默认取最高版本;`resolutionStrategy.force` 强制指定。

  • exclude 剔除传递依赖;`api` 与 `implementation` 区别:

  • api:依赖会传递给使用方(编译期可见)。

  • implementation:不传递(编译隔离,提升构建速度与封装)。

10. Baseline Profiles 是什么?

  • 提前记录关键代码路径(启动、滑动),AGP 编译成 dex 的高优先级机器码。

  • 首次启动即可享受接近 AOT 的性能,提速 20%~30%。

  • Macrobenchmark 自动生成,Jetpack 库自带 profile。


五、NDK / JNI / C++ 基础

1. JNI 的基本用法与签名规则?

```c

extern "C" JNIEXPORT jstring JNICALL

Java_com_x_Foo_nativeMethod(JNIEnv *env, jobject thiz) {

return env->NewStringUTF("hello");

}

```

  • 命名:Java_包名_类名_方法名(下划线转义 _1)。

  • 方法签名:`(I[Ljava/lang/String;)V`,javap -s 可查。

2. JNI 局部引用与全局引用?

  • 局部引用:方法返回后自动释放,但循环中大量创建会溢出(DeleteLocalRef)。

  • 全局引用:手动 NewGlobalRef / DeleteGlobalRef,跨方法持有(如回调 Java)。

  • 弱全局引用:不阻止 GC,用前需 IsSameObject 检查。

3. JNIEnv 是否线程安全?

  • JNIEnv 与线程绑定,不能跨线程缓存使用。

  • 可缓存 JavaVM(AttachCurrentThread / DetachCurrentThread)。

  • 后台线程回调 Java:Attach → GetMethodID → CallVoidMethod → Detach。

4. so 库与 ABI 是什么?

  • ABI(Application Binary Interface):arm64-v8a、armeabi-v7a、x86、x86_64。

  • abiFilters 指定打包哪些;只打 v8a 会显著减小体积(模拟器/旧设备需兼容)。

  • 64 位要求:Play 强制提供 arm64 版本。

5. C++ 智能指针?

  • unique_ptr:独占所有权,不可拷贝可移动。

  • shared_ptr:引用计数共享,循环引用需 weak_ptr 打破。

  • make_shared 一次分配对象与计数块,更高效。

6. C++ 虚函数与虚表(vtable)?

  • 虚函数实现运行时多态:对象头部存 vptr 指向虚函数表。

  • 子类覆写后表项替换,调用时查表。

  • 构造函数不能是虚函数(对象未建好无 vptr);析构函数基类必须是虚函数(否则 delete 父指针不调用子析构)。

7. Native 崩溃如何排查?

  • tombstone 文件(/data/tombstones/):addr2line / ndk-stack 符号化。

  • ndk-stack -sym 路径 直接解析崩溃堆栈。

  • Breakpad / xCrash 跨平台捕获 minidump。

  • 发布版本保留 so 的 unstripped 符号表用于还原。

8. Native 内存泄漏如何排查?

  • ASan(AddressSanitizer):编译期插入检测,查越界/UAF。

  • malloc_debug:运行时 hook malloc。

  • Android Profiler 的 Native Memory Record(记录调用栈分配)。

9. ANR / 崩溃信号机制?

  • Native 崩溃本质是信号(SIGSEGV/SIGABRT/SIGBUS)。

  • 注册 sigaction 捕获 → 保存上下文 → fork 子进程 dump(避免死锁)。

  • Java 崩溃走 Thread.setDefaultUncaughtExceptionHandler。

10. CMake 与 CMakeLists 常用配置?

```cmake

cmake_minimum_required(VERSION 3.22)

add_library(native SHARED native.cpp)

target_link_libraries(native android log)

```

  • externalNativeBuild 接入 AGP;find_library 引用 NDK 库(log、jnigraphics)。

六、音视频开发

1. 音视频播放的完整链路?

协议层(RTMP/HLS/HTTP)→ 封装层(FLV/MP4/TS)解封装 → 编码层(H264/AAC)解编码 → 像素/PCM → 渲染(OpenGL/AudioTrack)。

2. I 帧、P 帧、B 帧的区别?

  • I 帧:关键帧,完整图像,可独立解码。

  • P 帧:参考前面的帧,存差值。

  • B 帧:参考前后帧,压缩率最高但需要缓冲、增加延迟。

  • 直播为低延迟通常关 B 帧;seek 只能定位到 I 帧(GOP)。

3. 视频硬编与软编的区别?

  • 硬编:MediaCodec 调用 GPU/DSP,功耗低速度快,但机型兼容性差。

  • 软编:FFmpeg/x264 CPU 编码,兼容好但发热、性能差。

  • 生产实践:优先硬编,失败回退软编。

4. MediaCodec 的工作流程?

  • 生产者-消费者模型:InputBuffer 队列 + OutputBuffer 队列。

  • dequeueInputBuffer → fill → queueInputBuffer → dequeueOutputBuffer → render/release。

  • 异步模式 setCallback(API 21+)。

5. 如何实现一个美颜/滤镜相机?

  • CameraX 拿 YUV → 转 RGBA(或直接 ImageFormat)→ OpenGL ES 纹理(FBO)→ shader 处理(磨皮/滤镜)→ 显示到 SurfaceView 或编码 MediaCodec 输入 Surface。

  • 磨皮:双边滤波保边缘;大眼瘦脸:网格顶点形变(局部位移 shader)。

6. FFmpeg 常用命令行与 API?

  • 命令:`ffmpeg -i in.mp4 -vf scale=640:-1 -c:v libx264 out.mp4`

  • API:avformat_open_input → avformat_find_stream_info → avcodec 找解码器 → av_read_frame 循环 → avcodec_send/receive_packet → sws_scale 转格式。

7. 直播架构与常见协议对比?

| 协议 | 延迟 | 特点 |

|------|------|------|

| RTMP | 1-3s | 推流主流,TCP |

| HTTP-FLV | 2-4s | 拉流,防火墙友好 |

| HLS | 5-20s | 切片 m3u8,弱网稳 |

| WebRTC | <500ms | UDP,实时连麦 |

8. 音频焦点(AudioFocus)如何处理?

  • 请求焦点 requestAudioFocus,根据 LOSS_TRANSIENT/LOSS 暂停或降音量。

  • 播放前申请,停止时 abandonAudioFocus。

  • AudioAttributes 标注用途(音乐/通话/提示音)影响混音策略。

9. AudioTrack 播放的四种模式?

  • MODE_STATIC:一次性写入缓冲,适合短提示音(延迟低)。

  • MODE_STREAM:流式写,适合长音频/语音实时。

  • 采样率需匹配设备(48kHz 常见),格式 ENCODING_PCM_16BIT。

10. 如何做音视频同步?

  • 基准选择:音频为主(人耳敏感)或系统时钟。

  • PTS 换算:`pts * time_base` 秒。

  • 视频慢了 → 丢帧/加快渲染;快了 → 等待。

  • 参考实现:ffplay 的 sync 类型(audio/video/external clock)。


七、图形渲染系统

1. VSync 信号与 Choreographer?

  • 显示器每 16.6ms(60Hz)发 VSync。

  • Choreographer 通过 FrameDisplayEventReceiver(native 回调)接收 VSync。

  • postCallback 分发 CALLBACK_INPUT → ANIMATION → TRAVERSAL(measure/layout/draw)。

  • doFrame 计算掉帧(时间差 vs 16.6ms)。

2. 为什么用双缓冲/三缓冲?

  • 双缓冲:前台缓冲显示、后台缓冲绘制,VSync 时交换,防撕裂。

  • 三缓冲:CPU/GPU/Display 各占一个,减轻 jank(代价是延迟一帧)。

  • Android 4.1 Project Butter 引入 VSync 同步 + 三缓冲。

3. SurfaceFlinger 的工作流程?

  • 收集所有 Layer(App 的 Surface)。

  • VSync 到来时计算脏区,调用 OpenGL/合成器合成(HWC 硬件合成优先)。

  • 合成结果送 framebuffer 显示。

  • App 端 draw 只是往 Surface(BufferQueue)生产图形缓冲,SF 消费合成。

4. BufferQueue 生产者-消费者模型?

  • Surface(IGraphicBufferProducer):App 生产。

  • SurfaceFlinger(Consumer):消费合成。

  • acquire/dequeue + release/queue 一套异步流程,是 App 与显示系统解耦核心。

5. OpenGL ES 渲染管线?

顶点着色器 → 图元装配 → 光栅化 → 片元着色器 → 测试混合(深度/模板/Alpha)→ 帧缓冲。

  • GLSL 编写着色器;VBO/EBO 存顶点数据;FBO 离屏渲染(美颜中间处理)。

  • EGL 创建上下文与 Surface(GLSurfaceView 封装了这些)。

6. GLSurfaceView 与 TextureView 的区别?

| 项 | GLSurfaceView | TextureView |

|----|---------------|-------------|

| 实现 | 独立 Surface(View 层级之外) | 普通View,硬件加速层 |

| 性能 | 高 | 略低(额外合成) |

| 变换/动画 | 不支持(单独Window) | 支持平移缩放旋转 |

| 嵌套列表 | 有坑(与列表滑动冲突) | 可正常使用 |

7. RenderThread 与 HWUI?

  • 5.0 后 UI 绘制不再在主线程,draw 只是记录 DisplayList。

  • RenderThread 真正执行 GPU 命令(RenderProperties + DisplayListOp)。

  • 硬件加速默认开启;关闭则回退软件绘制(Skia 软栅格化)。

8. 硬件加速原理与禁用场景?

  • View 绘制指令录制为 DisplayList → RenderThread 通过 Skia (HWUI) 转 GPU 命令。

  • 优点:动画流畅(仅重录脏区)、减轻主线程。

  • 禁用场景:某些自定义 View 兼容问题(setLayerType SOFTWARE)、截图(缓存 bitmap)。

9. 自定义 View 如何做 GPU 友好?

  • 避免频繁创建 Paint/Path(对象池)。

  • 用硬件层 setLayerType(LAYER_TYPE_HARDWARE) 做复杂动画。

  • shader 尽量复用,避免每帧编译。

  • invalidate 最小化(脏矩形)。


八、热修复 / 插件化 / ClassLoader

1. Android 中的 ClassLoader 体系?

```

BootClassLoader(系统类)

PathClassLoader / DexClassLoader(应用类)

```

  • PathClassLoader:加载已安装 APK(/data/app)。

  • DexClassLoader:可加载任意路径 dex/apk/jar(旧版需 optimizedDirectory,8.0 后已废弃该参数)。

  • 二者 8.0 后实现一致(都走 DexPathList)。

2. 热修复的三大方案对比?

| 方案 | 原理 | 修复范围 | 代表 |

|------|------|----------|------|

| 类加载 | dex 插到 dexElements 前面 | 代码(需重启) | Tinker、Nuwa |

| 底层替换 | ArtMethod 替换入口点 | 方法(即时生效) | AndFix、Sophix |

| Instant Run | 类代理/分发 | 代码(即时) | Robust |

  • Tinker 补丁包最小(差量 dex),但需重启。

  • Sophix 综合两种:优先底层替换,失败退回类加载。

3. Tinker 的基本流程?

  1. 编译期:old dex 与 new dex 做 diff 生成 patch.dex。

  2. 运行时:下载补丁 → 合成全量 dex(合成在子进程)。

  3. 反射插入 dexElements0 → 重启生效。

  4. 类查找顺序改变,加载补丁中的新类。

4. 插件化如何加载插件的资源?

  • 反射构造 Resources:`ResourcesManager` 或 new AssetManager + addAssetPath(pluginPath)。

  • 构造插件自己的 Resources 实例(资源 id 冲突用动态 id 或资源分段)。

  • 四大组件插件化难点:

  • Activity:Hook IActivityManager 预占坑(stub)+ 还原。

  • Service:代理分发。

  • Provider:ContentProviderClient 包装。

  • Receiver:动态注册静态化。

5. Instant Run 的三类更新?

  • 热插拔:方法体修改,运行时替换(方法入口插桩)。

  • 温插拔:字段/签名变化需重启 Activity。

  • 冷插拔:结构变化,整个 APK 重启加载。

6. odex / vdex / art / oat 文件?

  • odex:优化后的 dex(系统预提取)。

  • oat:ART 编译产物(含机器码),ELF 格式。

  • vdex:验证过的 dex 副本(避免重复验证),9.0+。

  • art:方法入口地址/Profiling 信息。

7. Hook AMS 启动插件 Activity 的流程?

  1. 在 Instrumentation.execStartActivity 前替换 Intent:真实目标存 Bundle,Component 换成 Manifest 中预注册的占坑 Activity。

  2. AMS 校验通过后,ActivityThread 收到 LaunchActivityItem。

  3. 在 mInstrumentation.newActivity 前把 Component 还原为真实类。

  4. ClassLoader 用插件的 DexClassLoader 加载并实例化。

8. 如何检测插件 APK 的签名一致性?

  • PackageManager.GET_SIGNATURES / GET_SIGNING_CERTIFICATES 获取签名。

  • 对比字节码哈希,不一致拒绝加载(防替换攻击)。


九、安全与逆向

1. 常见加密算法分类与应用?

  • 对称:AES(加密数据)、DES(已不安全)、ChaCha20。

  • 非对称:RSA(交换密钥/签名)、ECC(更短密钥同强度)。

  • 摘要:MD5(已不安全)、SHA-256、HMAC(带密钥摘要)。

  • 典型:HTTPS 用 RSA/ECDHE 交换对称密钥,数据 AES-GCM 加密。

2. Android 应用加固方案与原理?

  • dex 加密:原 dex 加密藏在 so / 资源中,运行时解密后用 InMemoryDexClassLoader 加载。

  • so 加壳:OLLVM 混淆、VMP 虚拟机保护。

  • 资源混淆:AndResGuard 改短资源路径。

  • 防调试:ptrace 自附加、检测 frida/xposed。

3. 常见反编译工具与防护?

  • 工具:jadx、apktool、JEB、IDA、Frida(动态 hook)。

  • 防护:代码混淆 + 资源混淆、字符串加密、关键逻辑 native 化、完整性校验(签名校验)、反调试检测。

4. 如何防止网络被抓包?

  • SSL Pinning(证书锁定):OkHttp CertificatePatcher/sslSocketFactory 校验本地证书。

  • 双向认证(客户端证书)。

  • 关键参数签名 + 时间戳防重放。

  • 防止用户证书:Android 7+ 默认不信任用户 CA(networkSecurityConfig 控制)。

5. 数据存储加密方案?

  • 密钥存 AndroidKeyStore(硬件支持的 TEE/StrongBox),不可导出。

  • EncryptedSharedPreferences / EncryptedFile(Jetpack Security)。

  • 大数据:AES-GCM + Keystore 生成密钥加密随机数据密钥(信封加密)。

6. 防截屏与 FLAG_SECURE?

```java

getWindow().setFlags(FLAG_SECURE, FLAG_SECURE);

```

  • 截屏黑屏、不可见于最近任务预览(SurfaceFlinger 拒绝截取)。

  • 适用:支付、隐私页面。

7. AES 的几种模式与填充?

  • ECB:同明文同密文(不安全,暴露模式)。

  • CBC:需 IV,常见但并行性差。

  • GCM:带认证(AEAD),推荐,防篡改。

  • 填充:PKCS5Padding;密钥长度 128/192/256。

8. 什么是重打包攻击与防护?

  • 攻击:反编译 → 植入恶意代码/去广告 → 重签名 → 分发。

  • 防护:运行时校验自身签名哈希(native 校验更安全)、完整性自校验(关键文件哈希)、服务端二次校验。

9. 防自动化点击 / 群控?

  • 设备指纹(传感器噪声、GPU 渲染差异)。

  • 行为分析(滑动轨迹正态分布检测)。

  • SafetyNet/Play Integrity API 检测设备完整性。


十、动画体系

1. 补间动画(Tween)与属性动画(Property)区别?

  • 补间:只改显示效果(View 绘制层矩阵变换),不改变真实位置,点击事件仍在原地。

  • 属性:通过反射/Setter 真实改变属性值,作用于任何对象。

  • 属性动画核心类:ValueAnimator(值变化)与 ObjectAnimator(属性赋值)。

2. ValueAnimator 原理?

  • 内部 AnimationHandler 挂到 Choreographer 的 CALLBACK_ANIMATION。

  • 每帧根据 TimeInterpolator 与 TypeEvaluator 计算当前值,回调 onAnimationUpdate。

  • 与 UI 绘制同节奏,不额外开线程。

3. 插值器(Interpolator)与估值器(Evaluator)?

  • Interpolator:时间 → 进度比(如 AccelerateDecelerate)。

  • Evaluator:进度比 → 具体值(IntEvaluator、ArgbEvaluator 颜色渐变、自定义路径)。

4. Activity 切换动画的几种方式?

  • overridePendingTransition(旧版,5.0 前主流)。

  • ActivityOptions.makeCustomAnimation / makeSceneTransitionAnimation(转场动画)。

  • windowAnimationStyle 主题全局配置。

  • 共享元素转场:SharedElement + Transition(supportPostponeEnterTransition)。

5. Lottie 动画原理?

  • AE 导出 JSON(图层、关键帧、变换)。

  • Lottie 库解析为图层树,ValueAnimator 驱动进度,Canvas 绘制。

  • 优势:设计师直接导出、跨端一致、体积小;劣势:复杂效果性能不如原生/视频。

6. 如何优化动画卡顿?

  • 硬件层:动画期间 setLayerType(LAYER_TYPE_HARDWARE)(复杂视图才用,否则费显存)。

  • 用属性动画避免 invalidate 整棵树(如 translationX 走 RenderNode)。

  • 帧率监控:Choreographer/postOnFrameCallback 计算丢帧率。

  • 帧动画(AnimationDrawable)大图易 OOM → 用 SurfaceView 或 Lottie。


十一、WebView 深入

1. WebView 的加载流程?

`loadUrl` → WebChromeClient(进度/JS Dialog)→ WebViewClient(shouldOverrideUrlLoading / onPageFinished)→ 渲染。

2. JS 与 Native 通信方式?

  • JSBridge:`addJavascriptInterface`(4.2 以下有漏洞,需 @JavascriptInterface 注解)。

  • URL Scheme 拦截:shouldOverrideUrlLoading 解析自定义协议。

  • evaluateJavascript:Native 调 JS(4.4+,可拿返回值)。

  • WebMessagePort / postMessage(双向通道)。

3. WebView 内存泄漏怎么解决?

  • WebView 内部持有 Activity Context → 独立进程 + 杀进程。

  • 或 xml 动态创建(传 ApplicationContext)+ 从父容器 remove + destroy。

  • onDestory 中 destroy 的顺序:先 removeView,再 webview.destroy()。

4. WebView 白屏原因与排查?

  • 内核初始化未完成就加载(首次慢)→ 预热 WebView 池。

  • JS 错误阻塞渲染 → vConsole 调试。

  • 证书错误 → onReceivedSslError 处理(勿盲目 proceed)。

  • 资源跨域/CSP → onReceivedError 分类处理。

5. 如何调试 H5?

  • Chrome inspect(chrome://inspect)远程调试。

  • setWebContentsDebuggingEnabled(true)。

  • vConsole / eruda 注入到 H5。

6. WebView 缓存策略?

  • CACHE_DEFAULT:HTTP 缓存头控制。

  • LOAD_CACHE_ELSE_NETWORK:优先缓存,适合静态页。

  • 离线包:H5 资源本地化(zip 下发 + shouldInterceptRequest 拦截返回本地流)。


十二、跨平台技术

1. Flutter 与 RN 的架构区别?

| 项 | Flutter | React Native |

|----|---------|--------------|

| 渲染 | 自绘 Skia/Impeller,一致性强 | 原生组件映射(JSC/Hermes 桥接) |

| 语言 | Dart | JS/TS |

| 桥接 | 无桥(Platform Channel) | 旧架构 JS Bridge,新架构 JSI/TurboModule |

| 性能 | 接近原生(每帧直接 GPU) | 新架构已大幅改善 |

| 包体 | 较大(引擎 ~4MB) | 较小 |

2. Flutter 的渲染管线?

Widget(配置,不可变)→ Element(树,diff)→ RenderObject(布局/绘制)→ Layer → Scene → GPU。

  • setState 触发 markNeedsBuild → 下帧重建 subtree → 三棵树 diff(增量)。

3. Flutter Platform Channel 三种类型?

  • MethodChannel:方法调用(常用)。

  • BasicMessageChannel:双向消息。

  • EventChannel:事件流(如原生传感器数据流)。

  • 数据走 BinaryCodec,仅支持基本类型(需 JSON/protobuf 序列化复杂对象)。

4. 如何做 Flutter 与 Native 混编?

  • Add-to-App:Flutter Module 作为 AAR 嵌入原生。

  • FlutterFragment / FlutterView 嵌入页面。

  • 路由统一:FlutterBoost 栈管理(多引擎/单引擎+栈路由)。

5. KMP(Kotlin Multiplatform)适合什么场景?

  • 业务逻辑、网络层、数据层共享 Kotlin 代码。

  • UI 各端原生(或 Compose Multiplatform)。

  • 相比 Flutter:复用现有 Android 技术栈、无引擎开销,但生态较新。

6. 鸿蒙(HarmonyOS)与 Android 的区别?

  • 分布式架构(跨设备流转、软总线)。

  • UI:ArkTS/ArkUI 声明式(类似 Compose/SwiftUI)。

  • 应用形态:Ability(UI Ability / Data Ability)与 Android 四大组件不同。

  • 开发语言 ArkTS(TypeScript 扩展)。


十三、Framework 深入

1. SystemServer 启动了哪些核心服务?

  • AMS(ActivityManagerService)、PMS(PackageManagerService)、WMS(WindowManagerService)。

  • IMS(InputManagerService)、DMS(DisplayManagerService)、PowerManagerService。

  • 引导服务(BOOT_CLASS)→ 核心服务 → 其他服务三段启动。

2. 输入事件从硬件到 View 的流程?

  1. Linux input 驱动 → /dev/input/eventX。

  2. InputReader(EventHub 读)→ InputDispatcher。

  3. InputDispatcher 找到焦点窗口 → socketpair 发给 App 进程。

  4. ViewRootImpl 的 InputEventReceiver 收到 → InputStage 处理链 → DecorView dispatchTouchEvent → Activity。

3. 窗口的类型与 Z 序?

  • Application(Activity 窗口)、Sub(Dialog)、System(状态栏、Toast)。

  • type 值分三段:1-99 应用、1000-1999 子窗口、2000+ 系统窗口。

  • WMS 用 token 校验权限;SYSTEM_ALERT_WINDOW 需要 Settings.canDrawOverlays 授权。

4. Toast 的实现原理?

  • TN(ITransientNotification)是 Binder 回调。

  • NotificationManagerService 排队(每包最多 5 个),通过 TN.show 通知 App 端。

  • App 端 Handler 切主线程创建/显示(所以子线程 Looper.prepare 也能用)。

  • Toast 队列由系统控制,自定义时长只能 hack(反射 cancel 再 show)。

5. Dialog 为什么不能用 Application Context?

  • 创建 Dialog 时会通过 WindowManager 添加窗口。

  • Application 类型 token 不是应用窗口 token,type 校验失败抛 BadTokenException。

  • 例外:SYSTEM_ALERT_WINDOW 类型的 Dialog 可以用 Application Context(悬浮窗权限)。

6. Context 一共有多少个?

  • Application:每进程 1 个。

  • Activity:每个实例 1 个。

  • Service:每个实例 1 个。

  • BroadcastReceiver:onReceive 每次广播一个新的(生命周期几秒,不宜做耗时/弹窗)。

  • ContentProvider:与应用共享 Application Context。

7. Parcel 与 Serializable 的区别?

  • Serializable:Java 标准反射实现,产生大量临时对象、慢。

  • Parcelable:手写 writeToParcel/Creator,基于 Parcel(共享内存读写),快 10 倍。

  • Bundle 内部 ArrayMap 查找;跨进程传大对象有 1MB Binder 限制。

8. 什么是 System UI Flag(沉浸式)?

  • setSystemUiVisibility:LOW_PROFILE、FULLSCREEN、HIDE_NAVIGATION。

  • WindowInsetsController(新 API):hide(Type.systemBars())、setAppearanceLightStatusBars。

  • fitsSystemWindows 与 OnApplyWindowInsetsListener 处理布局避让。

9. Choreographer 掉帧监控如何实现?

```kotlin

Choreographer.getInstance().postFrameCallback { time ->

// 计算 lastTime 与 time 差值,超过阈值上报

Choreographer.getInstance().postFrameCallback(this)

}

```

  • 环形记录帧时间 → 慢帧/卡顿堆栈聚合上报(如 Matrix 的 EvilMethodTracer)。

10. 后台执行限制(Doze & App Standby)?

  • Doze:息屏+静止,延迟 Job/网络/唤醒,维护窗口批量执行。

  • App Standby:未使用 App 限制网络与 Job。

  • 豁免:前台、白名单、高优先级 FCM。

  • 适配:WorkManager setExpedited 加急任务。


十四、蓝牙 / 传感器 / 定位

1. BLE(低功耗蓝牙)开发流程?

  1. 权限:BLUETOOTH_SCAN/CONNECT(12+ 运行时)+ ACCESS_FINE_LOCATION(部分扫描场景)。

  2. BluetoothLeScanner.startScan 扫描。

  3. connectGatt 连接 GATT。

  4. discoverServices 发现服务 → getCharacteristic 读/写 → setCharacteristicNotification 订阅 notify。

  5. onCharacteristicChanged 收数据。

2. 经典蓝牙 vs BLE?

  • 经典:连续流(音频 A2DP、SPP),功耗高。

  • BLE:小数据包、极低功耗(手环、IoT)。

  • Android 12 新 API(BluetoothLeAdvertiser/BLE 批量扫描)。

3. 常见传感器与采样策略?

  • 加速度/陀螺仪(连续高频)、心率/温度(按需)、计步(硬件步数传感器,无需持续采样)。

  • SensorManager.registerListener 选 SamplingPeriodUs:游戏用 SENSOR_DELAY_GAME,日常 UI 用 UI。

  • 省电:onPause unregisterListener,或显著动作检测(SIGNIFICANT_MOTION)唤醒。

4. 定位方案对比?

| 方案 | 精度 | 耗电 |

|------|------|------|

| GPS | 高(10m) | 高 |

| 网络(基站/WiFi) | 中(百米) | 低 |

| 融合(FusedLocationProvider) | 自适应 | 最优 |

  • 后台定位需 ACCESS_BACKGROUND_LOCATION 单独授权。

  • Geofencing(地理围栏)由系统托管,App 被杀仍能唤醒。

5. NFC 的几种模式?

  • 读卡器模式(读 NFC 标签 NDEF)。

  • 卡模拟模式(HCE,Host Card Emulation 模拟门禁/公交卡)。

  • P2P 模式(Beam,已移除)。

  • Android Beam 8.0 废弃,改用 HCE。

6. USB / 串口通信?

  • UsbManager 枚举设备,请求权限(BroadcastReceiver 接收 ACTION_USB_PERMISSION)。

  • UsbInterface/UsbEndpoint 找到 bulk 端点,bulkTransfer 读写。

  • 串口:usb-serial-for-android 库封装 CDC/FTDI 等协议。


十五、测试与 CI/CD

1. 单元测试框架选择?

  • JUnit4 + Mockito(Mock 依赖)+ Robolectric(Android 环境模拟,跑 JVM)。

  • 纯逻辑用 JUnit,涉及 Framework 用 Robolectric,UI 用 Espresso/Compose Test。

2. 如何测试 ViewModel?

  • 注入假的 Repository(接口 + FakeImpl)。

  • kotlinx-coroutines-test 的 runTest + StandardTestDispatcher 控制虚拟时间。

  • Turbine 测试 Flow(`flow.test { awaitItem() }`)。

3. Espresso 与 UiAutomator 区别?

  • Espresso:同进程 UI 测试(白盒,快,可访问 ViewAction/IdlingResource 同步)。

  • UiAutomator:跨进程黑盒测试(可测系统 UI、第三方 App、解锁屏幕)。

4. 什么是依赖注入带来的可测试性?

  • 构造器注入替代内部 new,测试时传 Mock/Fake。

  • Hilt 提供 @BindValue + HiltAndroidTest 快速替换绑定。

5. CI/CD 流水线一般包含哪些阶段?

提交 → Lint/ktlint 静态检查 → 单元测试 → 构建 AAB/APK → 灰度/内测分发 → Play/Fir 发布 → 崩溃监控(Crashlytics/Sentry)闭环。

6. 如何做 A/B 测试?

  • Firebase Remote Config / GrowthBook 分流(按设备哈希分组)。

  • 指标埋点上报 → 统计显著性检验(t-test/Bayesian)。

  • 注意:分组一致性、样本量预估、防刷(真实用户过滤)。

7. Monkey 与稳定性测试?

  • adb shell monkey -p com.x --throttle 300 -v 5000。

  • 崩溃/ANR 日志抓取 → 分类归因。

  • Boost STF/Maxim 定向 Monkey(遍历业务关键路径)。


十六、操作系统与网络进阶

1. 进程与线程的区别?

  • 进程是资源分配单位(独立地址空间),线程是调度单位(共享进程资源)。

  • 上下文切换:进程切换需换页表/TLB,线程只需换寄存器和栈。

  • Android 每个 App 默认独立进程(Linux 进程 + Binder IPC)。

2. 用户态与内核态?

  • CPU 特权级区分,系统调用时陷入内核(trap)。

  • Binder 一次拷贝:用户态→内核共享区→对方用户态直接映射读取。

  • epoll/select 是内核态监听 fd 的机制。

3. 虚拟内存与页表?

  • 每进程有独立虚拟地址空间,MMU 通过页表映射物理内存。

  • 缺页中断:页不在物理内存时从磁盘/swap 加载。

  • mmap:文件映射到虚拟内存,读写文件无需 read/write 系统调用(MMKV 用)。

4. epoll 的优势?

  • select/poll:每次传入全部 fd,O(n) 遍历,上限受限。

  • epoll:红黑树管理 fd + 就绪链表回调,O(1) 获取就绪事件。

  • Android MessageQueue 的 nativePollOnce 即基于 epoll。

5. HTTP/2 的核心改进?

  • 二进制分帧(Header 压缩 HPACK)。

  • 多路复用(一个 TCP 并行多请求,无队头阻塞到应用层)。

  • 服务端推送(Chrome 已移除支持)。

  • TCP 层仍有队头阻塞 → HTTP/3 改用 QUIC(UDP)。

6. CDN 原理?

  • DNS 调度(GSLB)到边缘节点。

  • 边缘节点未命中回源拉取并缓存(Cache-Control 策略)。

  • 图片 CDN 可动态裁剪、WebP 转换、鉴权防盗链。

7. TCP 长连接与心跳(移动端)?

  • NAT 超时:运营商 NAT 表 5~10 分钟回收,需心跳(IM 常用 4~5 分钟智能心跳)。

  • 心跳包极小(仅协议头),前台/后台不同间隔。

  • 前后台切换、网络切换(WiFi→蜂窝)需重建连接。

8. 断点续传如何实现?

  • Range: bytes=start-end 请求头。

  • 响应 206 Partial Content + Content-Range。

  • 客户端记录已下载偏移;文件完整性用 ETag/If-Range 校验(避免文件变更后拼接错误)。


十七、Compose 进阶

1. 重组(Recomposition)的规则?

  • 状态读取(State<T>.value)发生在哪个 Composable,哪个就会重组。

  • 重组可能频繁且无序执行:Composable 必须无副作用。

  • @Stable/@Immutable 帮助编译器跳过不必要的重组(参数未变则跳过)。

2. remember 与 rememberSaveable?

  • remember:重组间保留(配置变更丢失)。

  • rememberSaveable:跨配置变更/进程死亡恢复(Bundle 机制,自动保存可 Bundle 化类型)。

3. 副作用 API 对比?

| API | 场景 |

|-----|------|

| LaunchedEffect(key) | 首次进入/ key 变化执行协程 |

| DisposableEffect | 需成对清理(注册/注销) |

| SideEffect | 每次重组后执行(同步外部状态) |

| rememberCoroutineScope | 事件回调中启协程 |

| snapshotFlow | 将 Compose 状态转 Flow |

4. Compose 性能优化?

  • 列表:LazyColumn + key(稳定 id,提升复用 diff 效率)。

  • derivedStateOf:减少由 state 计算的中间状态触发重组。

  • 避免不稳定参数(List 用 kotlinx.collections.immutable 或 @Immutable)。

  • 重组范围最小化:lambda 读状态而非整个函数读。

  • R8 + Compose Compiler Metrics 报告分析可跳过率。

5. Compose 与 View 互操作?

```kotlin

// Compose 中嵌 View

AndroidView(factory = { ctx -> MapView(ctx) }, update = { map -> ... })

// View 中嵌 Compose

ComposeView(context).apply { setContent { MyScreen() } }

```

  • 需要正确的 ViewTreeLifecycleOwner/ViewModelStoreOwner(ComponentActivity/Fragment 自动提供)。
  • navController 导航(rememberNavController)。

  • Bundle 传参与 restore(rememberSaveable + NavBackStackEntry)。

  • ViewModel 作用域绑定 NavBackStackEntry(hiltViewModel()),返回栈弹出自动销毁。


十八大厂场景设计题

1. 设计一个埋点 SDK(无埋点 + 代码埋点)?

  • 代码埋点:注解 + APT 生成收集类,或 API 直接上报。

  • 全埋点:Gradle 插桩(Transform/ASM)在 onClick/onPageResume 注入。

  • 缓存:内存队列 → 批量落盘(mmap 防丢)→ 定时/定量上报。

  • 可靠性:失败重试、本地保留(数据库)、压缩(protobuf+gzip)。

  • 动态配置:远端开关控制采样率。

2. 设计一个 Crash 捕获与上报系统?

  • Java:Thread.setDefaultUncaughtExceptionHandler 链式接管,先缓存再交回原 handler。

  • Native:信号量捕获 fork 子进程 dump tombstone。

  • ANR:Watchdog 线程 + traces.txt 监听。

  • 上报:补充设备信息、页面栈、最近操作日志 → 压缩上传 → 符号表还原(mapping.txt 管理)。

  • 平台:Crashlytics / Sentry / Bugly 或自研聚合(聚类归因 + 版本趋势)。

3. 设计抖音的无限滑动信息流?

  • 预加载:前后各 1 个视频(PagerAdapter/Compose Pager)。

  • 播放策略:可见 >50% 播放,离开立即停止释放解码器。

  • 缓存:磁盘 LRU(视频分片 Range 加载),滑太快时先显示首帧。

  • 内存:同屏最多 2-3 个解码实例,TextureView 池化。

  • 指标:卡顿率(播放起播时间)、秒开率监控上报。

4. 设计微信朋友圈的图片九宫格上传?

  • 压缩策略:长边 1280、质量 80、WebP 兼容回退 JPEG。

  • 并发控制:同时上传 3 个,失败重试指数退避。

  • 断点续传:分片 + Range。

  • 一致性:本地先占位(灰块),上传成功后替换 URL,失败标记重传。

  • 弱网:切 WiFi 提示、蜂窝默认原图不传仅传缩略图。

5. 设计一个灰度发布系统?

  • 维度:设备(哈希取模)、用户 ID 白名单、地区、版本。

  • 配置下发:长连接推送 + 定时拉取兜底。

  • 熔断:崩溃率/ANR 率超阈值自动停发。

  • 监控大盘:新版本 vs 旧版本核心指标对比。

6. 设计一个 App 内更新(热更新 + 强更)?

  • 版本策略:热修(Tinker patch)小改动;大功能走商店/自建 APK 下载。

  • 下载:前台服务通知进度、MD5 校验、断点续传。

  • 安装:FileProvider + ACTION_INSTALL_PACKAGE(8.0 需 REQUEST_INSTALL_PACKAGES 权限)。

  • 强更逻辑:服务端下发 minVersion,低于则弹不可关闭对话框。

7. 设计千万级日活 App 的配置中心?

  • 存储:SQLite(版本号 diff 增量更新)。

  • 下发:长连接推送即时生效 + 启动拉取(版本协商)。

  • 合并策略:多维度(渠道、地区、版本)交集合并。

  • 原子性:写临时文件 rename,防止配置损坏。

8. 如何设计页面路由表支持 DeepLink?

  • scheme/host/path 注册到路由表(ARouter @Route)。

  • 安全:白名单校验、防导出劫持(exported=false + 自定义校验)。

  • 延迟加载:PendingIntent 拉起时区分冷/热启动。

  • 兜底:目标页面不存在时跳转 Web 版或首页。


十九、HR 面与软技能

1. 自我介绍怎么说?

结构:基本信息(年限+方向)→ 技术亮点(2-3 个与岗位匹配的关键词)→ 代表项目(一句话量化成果)→ 求职动机。

控制在 1-2 分钟,重点前置。

2. 离职原因怎么回答?

  • 公式:客观发展诉求 + 向前看(不贬低前司)。

  • 示例:业务方向调整后技术成长受限,希望在 XX 方向更深的团队发展。

  • 避免:吐槽领导/加班/薪资(除非对方主动且策略表达)。

3. 你有什么缺点?

  • 说真实但不致命的缺点 + 正在改进的行动。

  • 示例:以前过度追求细节导致排期紧张,现在会用四象限拆分任务优先级。

4. 为什么选择我们公司?

  • 提前研究:产品、技术栈、团队(官网/招聘 JD/技术博客)。

  • 结合自身:方向匹配 + 价值贡献 + 成长空间。

5. 职业规划?

  • 短期(1-2 年):深耕某方向成为团队骨干。

  • 中期(3-5 年):技术专家 or 管理两条路(按 JD 倾向表述)。

  • 展现稳定性和自驱力。

6. 期望薪资如何谈?

  • 提前调研市场(脉脉/Offershow/拉勾薪酬报告)。

  • 给区间不给死数:"期望 XX-XX,具体结合职责与整体包综合评估。"

  • 谈总包(base+奖金+期权),不是只谈月薪。

7. 反问环节问什么?

  • 这个岗位当前最需要解决的三个问题?

  • 团队的技术栈与协作方式(敏捷节奏/代码评审文化)?

  • 入职后前三个月的核心目标?

  • 避免一上来问薪资福利加班(终面 HR 环节再问)。

8. 如何应对压力面?

  • 保持冷静,对方质疑时先认同合理部分再陈述事实。

  • 不懂的问题坦诚 + 给出思考路径(比胡编更加分)。

  • 把对抗转化为讨论:"您说的角度我之前没考虑,如果按这个思路我会......"

9. 加班怎么看?

  • 表达结果导向:"我更关注交付效率,必要时为项目目标全力以赴;平时会通过自动化工具和流程优化减少无谓加班。"

10. Offer 选择逻辑?

  • 权重打分:成长空间 > 业务前景 > 技术栈匹配 > 薪资 > 通勤。

  • 问清:汇报线、团队规模、KPI 考核方式、试用期标准。

附录:进阶学习路线建议

  1. **源码阅读顺序**:Handler → View 三大流程 → RecyclerView 缓存 → OkHttp → AMS/WMS → Binder。

  2. **动手项目**:自己实现一个简化版图片框架 / 热修复 / 路由框架,面试远超八股。

  3. **关注趋势**:Compose、KMP、Baseline Profiles、Macrobenchmark、AI 端侧(TFLite/MNN/NCNN)。

  4. **AOSP 环境**:能编译刷机 AOSP,阅读 frameworks/base 关键类加分极大。

  5. **输出习惯**:技术博客 / 内部分享,倒逼深度理解。

相关推荐
mmsx40 分钟前
osmdroid 自定义地图视图:继承 MapView 的正确姿势与生命周期管理
android·osmdroid
ii_best2 小时前
移动开发工具按键精灵安卓版 OcrEx 识别总是漏字错字?改这一个参数,精度直接翻倍
android·ai编程·按键精灵
chjif3 小时前
Android 设备管控开发实战:自定义 Launcher 如何只显示指定 App?
android·kotlin
Dovis(誓平步青云)3 小时前
模拟器横评:电脑上看小说、追短剧用什么模拟器?MuMu、雷电、腾讯手游助手实测
android·java·服务器·前端·javascript·电脑
非凡ghost3 小时前
用 Kotlin 和 Jetpack Compose 重写的安卓视频播放器,原生体验有多流畅?
android·java·kotlin·音视频·软件需求
峥嵘life4 小时前
Android16 系统 APEX 模块调试总结
android·大数据·开发语言
亘元有量-流量变现4 小时前
2026安卓ASO增量攻略:摆脱iOS思维依赖,吃透多商店自然免费流量
android·aso优化·亘元有量·方糖试玩
一航jason4 小时前
安卓车机端 AIOS 技术生态全景
android·人工智能·ai·ai编程·ai-native