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. **输出习惯**:技术博客 / 内部分享,倒逼深度理解。

相关推荐
tongyiixiaohuang10 小时前
WMS已发货状态反写金蝶云星空:单策略实战教程
android
好的佩奇11 小时前
Dart 之类修饰符
android·flutter·dart
alexhilton12 小时前
用Konsist与Lint强制执行设计系统契约
android·kotlin·android jetpack
唐青枫15 小时前
Kotlin Delegation 委托详解
kotlin
北京自在科技16 小时前
谷歌安卓 Gemini 迎来界面改版,Find Hub 接入 Gemini 支持物品记忆查找
android·安卓
YB137518 小时前
Jetpack Compose 动画Modifier.animateItem()
android
2401_8858850419 小时前
巴林语音通知接口如何对接?系统告警语音API接入教程
android·前端·网络·python·语音识别
收纳过往20 小时前
数据库加索引的时机:慢查询日志说话
android·开发语言·数据库·python·低代码·rxjava
狂热开发者21 小时前
车载中控要给鸿蒙用户,能不能和 Android 共用一个二维码?
android·华为·harmonyos
.Bryce.21 小时前
T2-LLM评测不等于Agent评测
android·java·人工智能·后端·gpt·agent·1024程序员节