栏目录导航
- [第 1 篇] 2026年 Android基础面试题全面汇总(50题)
- [第 2 篇] 2026年 Android进阶面试题全面汇总(50题)
- [第 3 篇] 2026年 Android高级面试题全面汇总(50题)
[第 1 篇] Android基础面试题全面汇总(50题) 内容覆盖了 Java/Kotlin 基础、Android 核心基础、Flutter 基础、网络/IM/音视频基础 以及 性能优化/工具基础。
一、 Java & Kotlin 基础(10题)
1. Java 中 String、StringBuilder 与 StringBuffer 的区别是什么?
-
答案:
-
String是不可变类(final),每次修改都会生成新的String对象,频繁拼接效率低且消耗内存。 -
StringBuilder是可变字符序列,非线程安全,性能最高,适用于单线程大量字符串拼接。 -
StringBuffer同样是可变字符序列,内部方法使用了synchronized修饰,是线程安全的,但性能略低于StringBuilder。
-
2. Java 的强引用、软引用、弱引用和虚引用有什么区别?
-
答案:
-
强引用 (StrongReference) :最常见的引用(如
Object obj = new Object())。只要强引用存在,GC 就绝不会回收该对象;当内存不足时宁可抛出 OOM。 -
软引用 (SoftReference) :只有在系统内存不足(即将 OOM)时,GC 才会回收软引用对象。常用于缓存。
-
弱引用 (WeakReference) :只要发生 GC,无论内存是否充足,弱引用对象都会被回收。常用于防止内存泄漏(如 Handler)。
-
虚引用 (PhantomReference) :随时可能被回收,形同虚设,不能单独用来获取对象实例。必须配合
ReferenceQueue使用,主要用来跟踪对象被垃圾回收的活动。
-
3. Java 集合框架中 HashMap 的底层实现原理及扩容机制是什么?
-
答案:
-
底层实现:JDK 1.8 中为“数组 + 链表 + 红黑树”。当链表长度大于等于 8 且数组长度大于等于 64 时,链表会转为红黑树;当红黑树节点数降为 6 时又会退化为链表。
-
扩容机制:默认初始容量为 16,加载因子为 0.75(即阈值 Threshold = 16 * 0.75 = 12)。当元素数量超过阈值时进行 2 倍扩容,扩容后需要重新计算元素下标(通过
hash & (newCap - 1)快速定位)。
-
4. Kotlin 中 val 和 var 的区别?const val 和 val 有什么区别?
-
答案:
-
val定义只读变量(相当于 Java 中的final变量),仅能赋值一次;var定义可变变量。 -
const val声明编译期常量,必须在类顶层或object/companion object中声明,且只能是基本数据类型或String;val是运行期只读属性,可以通过 getter 动态返回值。
-
5. Kotlin 的空安全机制是如何实现的??、!! 和 ?: 各代表什么?
-
答案:
-
空安全:Kotlin 在类型系统中区分了可空类型(如
String?)和不可空类型(如String)。编译期会进行强类型检查,并在字节码级别插入Intrinsics.checkNotNullParameter方法校验。 -
符号解释:
-
?:安全调用运算符,若对象为 null 则不执行后面的调用直接返回 null(如str?.length)。 -
!!:非空断言运算符,强行将可空类型转成不可空类型,若对象为 null 则抛出NullPointerException。 -
?::Elvis 运算符,若左侧表达式结果为 null,则返回右侧的值(如str?.length ?: 0)。
-
-
6. Kotlin 中的 sealed class(密封类)有什么作用和特点?
-
答案:
-
作用:表示一种受限的类继承结构,常用于定义 MVI/MVVM 架构中的 State 或 Intent。
-
特点:
-
密封类的所有子类必须在编译期已知(同文件或同一包名下)。
-
配合
when表达式使用时,编译器能穷举所有子类分支,不需要写else分支。 -
构造函数默认是
protected或private,无法在外部直接实例化。
-
-
7. 什么是 Kotlin 的扩展函数?它的底层实现原理是什么?
-
答案:
-
定义:允许在不修改原类代码、不使用继承的情况下,为现有的类添加新的函数。
-
底层原理:扩展函数本质上是静态方法(
public static final),该方法的第一个参数就是被扩展的对象实例(即this接收者)。由于是静态解析,扩展函数不支持多态重写,其调用由编译期变量的静态类型决定。
-
8. Kotlin 中的 apply、let、run、also、with 作用域函数有什么区别?
-
答案:
-
let:上下文对象是it,返回值是 Lambda 表达式的最后一行。常用于空校验和链式调用。 -
apply:上下文对象是this,返回值是 对象本身。常用于对象的初始化和属性配置。 -
run:上下文对象是this,返回值是 Lambda 表达式的最后一行。 -
also:上下文对象是it,返回值是 对象本身。常用于附加操作(如打印日志)。 -
with:非扩展函数,接受对象作为参数,上下文对象是this,返回值是 Lambda 表达式的最后一行。
-
9. 什么是 Kotlin 协程?它和线程有什么区别?
-
答案:
-
定义:协程可以看作是“轻量级的线程”,本质上是由用户态调度的并发编程框架,运行在 JVM 线程之上。
-
区别:
-
线程是操作系统调度的 CPU 最小单位,切换成本高(需保存内核上下文);协程由用户态代码(协程调度器)控制,切换开销极小。
-
协程通过“挂起(suspend)”与“恢复(resume)”机制实现非阻塞式异步编程,不会阻塞底层绑定的线程。
-
-
10. Java/Kotlin 中的线程同步机制有哪些?(从 synchronized 到 ReentrantLock)
-
答案:
-
synchronized:Java 内置关键字,基于 JVM Monitor(监视器)实现。支持偏向锁、轻量级锁、重量级锁的锁升级过程;支持自动加锁与解锁。 -
ReentrantLock:基于 AQS(AbstractQueuedSynchronizer)实现的重入锁,灵活性高于synchronized。支持公平锁与非公平锁、可中断响应、超时获取锁以及配合Condition实现多路等待/通知机制。 -
Kotlin 中还可以使用并发包的
Atomic原子类、协程中的Mutex(互斥锁,挂起而非阻塞线程)以及Channel/Flow通信机制。
-
二、 Android 核心基础(15题)
11. 简述 Activity 的生命周期及异常重建流程。
-
答案:
-
正常生命周期:
onCreate()->onStart()->onResume()-> [运行中] ->onPause()->onStop()->onDestroy()。 -
异常重建:当配置变更(如屏幕旋转)或系统内存不足导致 Activity 被杀时,系统会回调
onSaveInstanceState(Bundle)保存数据。重新创建时,会依次执行onCreate(Bundle)和onRestoreInstanceState(Bundle),可以将 Bundle 中的状态恢复。
-
12. Fragment 的生命周期是怎样的?add 和 replace 有何区别?
-
答案:
-
生命周期:
onAttach->onCreate->onCreateView->onViewCreated->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach。 -
区别:
-
add():将 Fragment 叠加添加到容器中,原 Fragment 依然存活,UI 也处于可见/隐藏状态,生命周期不会销毁。 -
replace():先将容器中的现有 Fragment 全部移除(依次触发onDestroyView到onDetach),再添加新的 Fragment。
-
-
13. Service 有哪两种启动方式?它们的生命周期和应用场景有什么不同?
-
答案:
-
startService():-
生命周期:
onCreate()->onStartCommand()-> [运行] ->onDestroy()。 -
特点:与调用者生命周期无解耦,调用者退出后 Service 依然后台运行。用于执行不需要交互的后台任务(如后台文件下载)。
-
-
bindService():-
生命周期:
onCreate()->onBind()-> [通信] ->onUnbind()->onDestroy()。 -
特点:与调用者绑定,调用者退出时自动解绑,可获取 IBinder 进行跨进程/本地通信。
-
-
14. 简述 Android 事件分发机制的三大核心方法及分发顺序。
-
答案:
-
三大核心方法:
-
dispatchTouchEvent(MotionEvent ev):负责事件的分发。 -
onInterceptTouchEvent(MotionEvent ev):ViewGroup 独有,负责事件的拦截(返回 true 表示拦截)。 -
onTouchEvent(MotionEvent ev):负责事件的处理(返回 true 表示消耗该事件)。
-
-
分发顺序:Activity -> PhoneWindow -> DecorView -> ViewGroup -> View。下发时自上而下询问是否拦截,若无人拦截并到达最底层的 View 且
onTouchEvent返回 false,则事件向上回溯冒泡交由上层 ViewGroup/Activity 处理。
-
15. 请详细解释 Android Handler 消息机制(Handler, Looper, MessageQueue, Message)。
-
答案:
-
Message:消息载体,内部持有target(Handler 引用)和callback。 -
MessageQueue:消息队列,基于单链表结构按执行时间(when)排序存储 Message。 -
Looper:消息循环器,每个线程最多一个。通过Looper.loop()死循环调用MessageQueue.next()取出消息,并将 Message 交给其target(Handler)的dispatchMessage()分发处理。 -
Handler:消息的发起者与处理者,负责通过sendMessage()将 Message 入队到 MessageQueue,并在handleMessage()中回调处理消息。
-
16. View 的绘制流程包含哪三个主要阶段?各自的作用是什么?
-
答案:
-
onMeasure(int widthMeasureSpec, int heightMeasureSpec):测量 View 的宽高尺寸。基于父容器传入的 MeasureSpec(EXACTLY, AT_MOST, UNSPECIFIED)计算自身的宽高。 -
onLayout(boolean changed, int left, int top, int right, int bottom):确定 View 在父容器中的最终位置(摆放坐标)。 -
onDraw(Canvas canvas):将 View 绘制到屏幕上。通常依次绘制背景、内容(onDraw)、子 View(dispatchDraw)和装饰(如滚动条)。
-
17. 什么是 View 的 invalidate() 和 requestLayout()?它们有什么区别?
-
答案:
-
invalidate():触发 View 的重绘(重走onDraw()),不会重新触发onMeasure()和onLayout()。适用于仅修改了背景颜色、文本内容等不改变大小和位置的情况。 -
requestLayout():触发 View 重新测量和布局(重走onMeasure()->onLayout()->onDraw()),适用于 View 的尺寸、外边距或隐藏状态改变时。
-
18. Android 中的 RemoteViews 适用于什么场景?其工作原理是什么?
-
答案:
-
应用场景:常用于通知栏 Notification 和桌面小组件 AppWidget。
-
原理:RemoteViews 实现了
Parcelable接口,可以在跨进程(IPC)中传输。它并不是真正的 View,而是一套 UI 描述指令。底层通过 Binder 将描述传递给系统服务(如NotificationManagerService),由系统服务在自己的进程解析并在指定的 View 层次树上应用这些绘制操作。
-
19. 简述 Context 的体系结构,Activity、Service 和 Application 的 Context 有何区别?
-
答案:
-
体系结构:
Context为抽象基类,ContextImpl是其具体实现类;ContextWrapper为包装类,Application、Service继承自ContextWrapper;ContextThemeWrapper继承自ContextWrapper,Activity继承自ContextThemeWrapper。 -
区别:
-
Activity含有 Theme(主题)信息,适用于 UI 弹出(对话框)、启动 Activity 等操作。 -
Service和Application没有 Theme 资源,不能直接用于弹出 Dialog 或依赖 Theme 的 View 渲染。启动 Activity 时通常需要加FLAG_ACTIVITY_NEW_TASK标记。
-
-
20. Android 四大组件在 AndroidManifest.xml 中注册的意义是什么?
-
答案:
-
清单文件是 AMS(ActivityManagerService)及系统解析 APK 的清单。
-
注册组件可以让系统 AMS 知道该应用暴露了哪些组件、权限要求、启动模式及 IntentFilter 过滤规则。未在 Manifest 中注册的 Activity 启动时会被 AMS 校验拒绝,抛出
ActivityNotFoundException。
-
21. Android 中的 Parcelable 和 Serializable 序列化接口有何区别?
-
答案:
-
Serializable:Java 原生接口,基于反射实现,序列化过程中产生大量临时对象并伴随频繁磁盘 I/O,效率较低。 -
Parcelable:Android 特有接口,内存型序列化,将对象打散存储到内存块(Parcel)中,高效且适用于 Binder IPC 跨进程传输,但编写繁琐(Kotlin 中可用@Parcelize简化)。
-
22. 什么是 ComponentActivity、FragmentActivity 和 AppCompatActivity?
-
答案:
-
ComponentActivity:Jetpack 的基础 Activity 类,实现了LifecycleOwner、ViewModelStoreOwner、SavedStateRegistryOwner等基础能力。 -
FragmentActivity:继承自ComponentActivity,增加了对原生 Fragment 兼容与调度的支持。 -
AppCompatActivity:继承自FragmentActivity,向下兼容旧版本 Android 的 Material 设计风格、ActionBar 以及 AppCompat 系列控件。
-
23. Jetpack ViewModel 的作用是什么?为什么屏幕旋转时它不会销毁?
-
答案:
-
作用:负责存放和管理 UI 相关的数据,实现 UI 与数据解耦,并自动感知的生命周期。
-
屏幕旋转不销毁原理:屏幕旋转导致 Activity 销毁重建时,系统在销毁前通过
ViewModelStore将 ViewModel 实例留存(存储在NonConfigurationInstances中)。Activity 重建后,从新的ViewModelStore中通过相同的 Key 取出之前的 ViewModel 实例。只有当 Activity 真正 finish 时,才会调用ViewModel.onCleared()释放资源。
-
24. LiveData 和 StateFlow 有什么区别?
-
答案:
-
LiveData:Android 架构组件,UI 感知(生命周期感知),只在 Observer 处于STARTED/RESUMED状态时发送更新,主要在 Android 主线程(UI 线程)使用。 -
StateFlow:Kotlin 协程生态提供的响应式数据流,属于热流,无 Android 平台依赖(纯 Kotlin);必须有初始值,始终保留最新状态;支持丰富的协程操作符(如map、filter等),需结合repeatOnLifecycle在 Android UI 中安全监听。
-
25. 什么是 Android 组件化开发?组件化与模块化的区别是什么?
-
答案:
-
模块化:侧重于按照业务(如用户模块、商品模块)或功能(如网络库、图片库)将代码结构拆分为不同 module,但最终仍编译在一个大工程中,模块间可能存在直接依赖。
-
组件化:在模块化的基础上进一步彻底解耦。每个组件不仅是独立的 module,且可以作为单独的 App 运行调试(通过切换
isApp标记);组件之间不能直接依赖,必须通过路由(如 ARouter、WMRouter)或接口下沉的方式实现跨组件调用与通信。
-
三、 Flutter 基础(10题)
26. 简述 Flutter 的三棵树(Widget、Element、RenderObject)架构及作用。
-
答案:
-
Widget 树:配置文件,轻量级、不可变(Immutable),用于描述 UI 的配置信息(如颜色、布局属性)。
-
Element 树:Widget 与 RenderObject 之间的桥梁,持有 Widget 和 RenderObject 的引用,管理 Lifecycle。Element 树是可变的,当 Widget 更新时,通过 Diff 算法复用 Element。
-
RenderObject 树:真正负责布局(Layout)和绘制(Paint)的实体对象,开销较大,仅与 render 类的 Widget 对应。
-
27. Flutter 中 StatelessWidget 与 StatefulWidget 的区别及生命周期。
-
答案:
-
区别:
StatelessWidget适用于不可变状态的静态 UI;StatefulWidget拥有可变的State对象,可以通过setState()触发 UI 刷新。 -
StatefulWidget生命周期:createState()->initState()->didChangeDependencies()->build()->didUpdateWidget()(父组件重构时)->deactivate()->dispose()。
-
28. Flutter 中的 MethodChannel、EventChannel 和 BasicMessageChannel 有何区别?
-
答案:
-
MethodChannel:用于一次性方法调用(双向),通常由 Dart 发起请求,原生端返回异步结果。 -
EventChannel:用于数据流传输(单向,原生 -> Dart),通常用于原生端向 Dart 端持续推送事件(如传感器数据、网络状态变动、音视频进度等)。 -
BasicMessageChannel:用于连续的双向消息传递,支持自定义编解码器(如 String、JSON、二进制)。
-
29. Flutter 中的 SetState 局部刷新机制及 Keys 的作用是什么?
-
答案:
-
局部刷新:
setState()会将当前 State 标记为 dirty,并在下一个帧调度中重新触发该 State 的build()。为了避免大面积重构,可以将需要刷新的控件抽取成独立的StatefulWidget或使用ValueNotifier/Builder包装。 -
Keys 的作用:在 Widget 树发生结构变化(如列表项增删、排序)时,帮助 Flutter 识别 Element 与 Widget 的对应关系,保证状态(State)能正确保留和绑定到对应的 Widget 上。
-
30. 简单对比 GetX 和 Riverpod 两种状态管理框架的特点。
-
答案:
-
GetX:高集成度、易上手,采用响应式(
Rx)/单例驱动;内置路由管理、国际化、依赖注入等功能;缺点是隐式依赖较多、解耦不够彻底。 -
Riverpod:基于 Provider 升级重构,编译期安全,完全脱离了 BuildContext 树限制;支持代码生成(Riverpod Generator),状态声明式且易于测试,架构设计更符合现代 Dart 标准。
-
31. Flutter 中的 Future 和 Isolate 是什么?它们有什么区别?
-
答案:
-
Future:基于 Dart 异步事件循环(Event Loop)机制实现的非阻塞任务,依然运行在同一个单线程(Main Isolate)中。适用于网络请求、文件 I/O 等异步等待。 -
Isolate:Dart 的多线程实现模型。每个 Isolate 都有独立孤立的内存空间和事件循环,Isolate 之间不共享内存,只能通过消息传递(ReceivePort/SendPort)通信。适用于耗时的计算密集型任务(如大 JSON 解析、图像处理)。
-
32. Flutter 的布局模型约束传递原则是什么?(Constraints go down, Sizes go up, Parents set positions)
-
答案:
-
Constraints go down:父节点向子节点传递约束条件(最小/最大宽高)。
-
Sizes go up:子节点根据父节点给出的约束,计算出自身的尺寸(Size)并汇报给父节点。
-
Parents set positions:父节点根据子节点的尺寸,决定子节点在自己坐标系中的位置(Position)。
-
33. Flutter 如何处理原生平台的权限申请(如 Camera、Microphone)?
-
答案:
-
通常使用插件
permission_handler。 -
在 Android 端的
AndroidManifest.xml和 iOS 端的Info.plist中声明静态权限。 -
在 Dart 端通过
Permission.camera.request()动态发起请求,并根据返回状态(granted、denied、permanentlyDenied)进行后续业务跳转或弹窗引导。
-
34. Flutter 中 ListView.builder 的优化原理是什么?
-
答案:
-
ListView.builder使用了懒加载(Lazy Loading)机制。 -
它不会一次性渲染列表中所有子 Widget,而是根据视口(Viewport)大小和预加载区域(
cacheExtent),仅对当前可见及邻近的少量子 Widget 进行构建与渲染;超出可见范围的 Element/RenderObject 会被回收复用,极大降低内存开销。
-
35. 什么是 Flutter 引擎(Engine)和 Dart VM?
-
答案:
-
Flutter Engine:纯 C/C++ 实现的高性能渲染引擎,包含 Skia/Impeller 图形渲染库、Text 文本排版引擎、Dart 运行时以及 Platform Channels 底层支持,负责将 Widget 绘制指令渲染为屏幕像素。
-
Dart VM:Dart 语言的虚拟机/运行时环境,在 Debug 模式下提供 JIT(即时编译)实现 Hot Reload,在 Release 模式下通过 AOT(预先编译)编译成机器码以获得极致性能。
-
四、 网络通信、IM & 音视频基础(8题)
36. TCP 协议中的“三次握手”和“四次挥手”过程分别是什么?
-
答案:
-
三次握手(建立连接) :
-
客户端发送 SYN,进入 SYN_SENT 状态。
-
服务端收到后回复 SYN + ACK,进入 SYN_RCVD 状态。
-
客户端收到后回复 ACK,进入 ESTABLISHED 状态,连接建立。
-
-
四次挥手(断开连接) :
-
客户端发送 FIN,进入 FIN_WAIT_1 状态。
-
服务端收到后回复 ACK,进入 CLOSE_WAIT 状态。
-
服务端处理完剩余数据后,发送 FIN,进入 LAST_ACK 状态。
-
客户端收到后回复 ACK,进入 TIME_WAIT 状态,等待 2MSL 后彻底关闭;服务端收到 ACK 后直接关闭。
-
-
37. WebSocket 协议与 HTTP 协议有什么区别和联系?
-
答案:
-
联系:WebSocket 借用 HTTP 协议的 101 Status Code(Switching Protocols)完成初始握手升级。
-
区别:
-
HTTP 是无状态、单向请求-响应式协议(客户端发起,服务端被动响应)。
-
WebSocket 是全双工通信协议,一旦握手建立后,客户端和服务端可以随时互相推送数据,头部开销小,适合高频实时交互(如 IM、直播弹幕)。
-
-
38. 什么是 Netty?它相比传统 Java Bio/Nio 有什么优势?
-
答案:
-
定义:Netty 是一个基于 NIO(非阻塞 I/O)的高性能异步事件驱动的网络通信框架。
-
优势:
-
封装了原生 Java NIO 繁琐且易出错的 API(如 Selector、ByteBuffer 读写切换)。
-
解决了原生 NIO 的 Epoll 空轮询 Bug。
-
自定义了高性能的 ByteBuf 内存缓冲区(支持池化和零拷贝 Zero-Copy)。
-
提供了丰富的编解码器(如 Protobuf、LengthFieldBasedFrameDecoder)和灵活的责任链管道(ChannelPipeline)。
-
-
39. IM 系统中“心跳机制”的作用是什么?
-
答案:
-
维持 TCP/WebSocket 长连接的存活,防止因移动网络运营商 NAT 映射超时(NAT 穿透失效)导致连接被切断。
-
及时探测网络异常断开(如假死、断网、突发无信号)。当客户端或服务端在指定时间内未收到对方的心跳回应时,能主动触发重连或清理失效连接。
-
40. 什么是音视频的 RTMP、HTTP-FLV 和 HLS 协议?
-
答案:
-
RTMP:基于 TCP 的私有实时消息协议,延迟极低(1-3秒),常用于直播推流;缺点是浏览器原生支持差,需借助 Flash 或 WASM。
-
HTTP-FLV:将 RTMP 封装成 FLV 流通过 HTTP 协议传输,延迟低(1-3秒),防火墙穿透性好,常用于国内直播拉流。
-
HLS:Apple 主导的基于 HTTP 的切片流协议(M3U8 索引文件 + TS 切片文件),兼容性极好(iOS/Android 原生支持),但延迟较高(10-30秒),常用于点播或对延迟不敏感的直播。
-
41. 音视频开发中的硬解码与软解码有何区别?
-
答案:
-
软解码:使用 CPU 运行纯软件算法(如 FFmpeg)解析音视频帧。优点是兼容性强、支持格式广;缺点是 CPU 占用高、发热严重、耗电量大。
-
硬解码:调用系统底层专属的硬件解码芯片(如 Android MediaCodec、iOS VideoToolbox)进行解码。优点是速度极快、CPU 占用极低、省电;缺点是不同芯片厂商兼容性存在差异。
-
42. 简单介绍播放器框架 ijkplayer 与 ExoPlayer 的区别。
-
答案:
-
ijkplayer:Bilibili 开源的基于 FFmpeg 的跨平台(Android/iOS)播放器,底层 C/C++ 占比高,对软解和自定义封装协议(如 FLV/RTMP)支持极佳,但社区停更较久。
-
ExoPlayer:Google 官方主导的 Android 端纯 Java/Kotlin 级可扩展播放器,深度集成 Android 系统硬解,支持 DASH、SmoothStreaming 等现代流媒体协议,扩展性极强,是 Android 官方推荐的标准播放库。
-
43. 简述 Protobuf 数据格式相比 JSON/XML 的优势。
-
答案:
-
体积更小:采用二进制编码(Varint、ZigZag 等变长编码技术),去除格式化标签和冗余空格,体积仅为 JSON 的 1/3~1/10。
-
解析速度更快:序列化/反序列化不需要复杂的文本解析过程,直接按字节索引偏移提取数据。
-
强类型约束:通过
.proto描述文件自动生成各语言代码,编译期防范类型不一致风险。
-
五、 性能优化与故障排查基础(7题)
44. 什么是 Android 中的 OOM(OutOfMemoryError)?常见的诱发原因有哪些?
-
答案:
-
定义:当应用向 JVM/Android 系统申请的内存超过了当前进程分配的上限(
heapsize),且 GC 无法回收足够空间时,抛出 OOM 异常。 -
常见原因:
-
大图/未压缩图片的直接加载( Bitmap 占用大量 Java 堆或 Native 内存)。
-
长期内存泄漏(如 Static 变量持有了 Activity Context、Handler 未移除消息、单例持有了 Activity)。
-
线程创建过多(超过系统进程线程上限)。
-
-
45. 什么是 ANR(Application Not Responding)?触发 ANR 的超时阈值分别是多少?
-
答案:
-
定义:应用主线程(UI 线程)在特定时间内未响应用户输入或未完成系统回调,导致系统弹出“应用无响应”提示框。
-
超时阈值:
-
KeyDispatching Timeout(按键/触摸事件):5 秒。
-
Service:前台 Service 20 秒,后台 Service 200 秒。
-
BroadcastReceiver:前台广播 10 秒,后台广播 60 秒。
-
ContentProvider:Publish 超时 10 秒。
-
-
46. 简述 Android 内存泄漏的含义,并举出 3 个常见的内存泄漏场景。
-
答案:
-
含义:生命周期较短的对象已经不再使用,但由于被生命周期更长的对象持有了强引用,导致 GC 无法正常回收该对象,使其长期驻留在内存中。
-
常见场景:
-
静态变量持有 Context:如静态单例持有了 Activity 的 Context。
-
非静态内部类/匿名内部类:如 Handler、Runnable、AsyncTask 默认持有外部 Activity 的引用,若延迟任务未执行完 Activity 就 finish,会导致 leak。
-
资源未注销/未关闭:如 RxJava 未
dispose()、EventBus 未unregister()、Cursor/FileStream 未close()。
-
-
47. Android 官方推荐的 Profiler 工具有哪些分析模块?各自有什么作用?
-
答案:
-
CPU Profiler:跟踪 CPU 使用率、分析线程状态,并通过 System Trace / Callstack 追踪方法耗时与卡顿。
-
Memory Profiler:实时监控堆内存分配(Heap Dump),抓取内存快照分析内存泄漏与对象数量。
-
Network Profiler:监控 HTTP/HTTPS 及 Socket 的网络请求数据量、耗时及响应流。
-
Energy Profiler:分析应用对设备电量(CPU、GPS、蓝牙等)的消耗。
-
48. 解释什么是过度绘制(Overdraw)?如何排查与解决?
-
答案:
-
概念:屏幕上的某个像素在同一帧内被重复绘制了多次。
-
排查方法:在 Android 开发者选项中开启“调试 GPU 过度绘制(Show GPU Overdraw)”,观察屏幕颜色(无色 < 蓝 < 绿 < 淡红 < 深红)。
-
优化方案:
-
移除不必要的控件背景色(如 Activity/Layout 重复设背景)。
-
扁平化布局层级,减少
ConstraintLayout或 nested view 的过度嵌套。 -
自定义 View 中使用
canvas.clipRect()剪裁出非重叠区域再绘制。
-
-
49. LeakCanary 的工作原理是什么?
-
答案:
-
LeakCanary 在 Activity/Fragment 销毁时(如
onDestroy),使用WeakReference弱引用关联该实例,并将弱引用注册到ReferenceQueue(引用队列)中。 -
主动触发一次垃圾回收(GC),若对象被正常 GC,其对应的弱引用会被加入到
ReferenceQueue。 -
延迟一段时间(通常 5 秒)后检查
ReferenceQueue,若队列中没有该弱引用,说明该对象依然存活(发生内存泄漏),随后触发 Heap Dump 生成.hprof文件并通过 Shark 库解析引用链,定位泄漏源头。
-
50. 什么是 Android 中的卡顿(Jank)?它的基本定义是什么?
-
答案:
- 定义:Android 系统要求屏幕刷新率通常为 60Hz(即每 16.6ms 刷新一帧)或 90Hz/120Hz。如果应用在主线程中执行了耗时操作(如复杂 UI 测量、主线程 I/O、大量对象创建),导致丢帧(Frames Drop),系统无法在规定时间(16.6ms)内准备好 Surface 缓冲区供 SurfaceFlinger 合成,就会造成画面停顿,即产生“卡顿(Jank)”。
栏目录导航
- [第 1 篇] 2026年 Android基础面试题全面汇总(50题)
- [第 2 篇] 2026年 Android进阶面试题全面汇总(50题)
- [第 3 篇] 2026年 Android高级面试题全面汇总(50题)
最后,祝愿每一位正在备战面试的 Android 开发者:
- 能够在反复的梳理与思考中打破瓶颈,将知识真正融会贯通;
- 在接下来的每一场面试中发挥出色、对答如流,展现出自己最出色的技术硬实力;
- 拨云见日,顺利斩获心仪的大厂与中高级职位 Offer,在移动开发的技术道路上披荆斩棘、一路高歌!