Android 之 面试八股文

  1. ​1.Activity生命周期​

    • ​问题​​:描述Activity从启动到销毁的完整生命周期方法,并说明onSaveInstanceState()的调用时机。

    • ​参考答案​​:

      • onCreate()→ onStart()→ onResume()(活跃状态) → onPause()(失去焦点) → onStop()(完全不可见) → onDestroy()

      • onSaveInstanceState():在Activity可能被销毁前调用(如屏幕旋转),用于保存临时数据到Bundle。

    • ​考察点​​:生命周期顺序、状态恢复、资源释放时机。

  2. ​2.Fragment通信方式​

    • ​问题​​:列举3种Fragment间通信方式,并对比优缺点。

    • ​参考答案​​:

      • ​ViewModel共享​​:通过同一Activity作用域的ViewModel共享数据(推荐,解耦性强)。

      • ​Fragment Result API​​:使用setFragmentResult()传递Bundle(无需直接引用)。

      • ​接口回调​​:Fragment定义接口,Activity实现并转发(代码冗余,适合简单场景)。

​3.View绘制流程​

    • ​问题​​:解释View的onMeasure()onLayout()onDraw()的作用,并说明如何优化自定义View的性能。

    • ​参考答案​​:

      • onMeasure():计算View尺寸(需处理MeasureSpec模式)。

      • onLayout():确定子View位置。

      • onDraw():绘制内容(避免在此创建对象或耗时操作)。

      • ​优化​​:使用ViewStub延迟加载、减少布局层级、启用硬件加速。

4.​​事件分发机制​

5.​​Handler机制​

6.解释下多线程编程

6.​​内存泄漏场景与解决​

    • ​问题​​:列举3个常见内存泄漏场景(如静态Context),并提供解决方案。

    • ​参考答案​​:

      • 静态Context → 改用ApplicationContext或弱引用。

      • 未注销广播 → 在onDestroy()中调用unregisterReceiver()

      • 匿名内部类持有外部引用 → 静态内部类 + 弱引用。

  1. ​7冷启动优化​

    • ​问题​​:应用冷启动耗时超过1秒,如何定位和优化?

    • ​参考答案​​:

      • ​定位工具​​:Android Studio Profiler的启动时间分析。

      • ​优化方案​​:

        • 延迟初始化第三方库(使用App Startup)。

        • 减少主线程任务(用线程池处理IO操作)。

        • 使用SplashScreen API避免白屏。

  1. 8.​​MVVM与MVI对比​

    • ​问题​​:解释MVVM和MVI架构的区别,并说明MVI如何解决状态管理问题。

    • ​参考答案​​:

      • ​MVVM​​:数据驱动UI(LiveData + ViewModel),但状态分散。

      • ​MVI​​:单向数据流(ViewState → 事件 → 更新状态),状态集中管理(如用Kotlin Flow实现)。

  2. ​模块化方案​

    • ​问题​​:如何将单模块App拆分为模块化架构?需考虑哪些问题?

    • ​参考答案​​:

      • ​步骤​​:按功能划分模块(登录、支付等),基础库抽离为独立Module。

      • ​关键点​​:

        • 依赖注入解耦(使用Hilt)。

        • 路由框架(如ARouter)解决跨模块跳转。

        • Gradle配置按需编译。

  1. 9.​​Binder机制​

    • ​问题​​:解释Binder在IPC中的一次拷贝原理,并说明其与Socket通信的性能差异。

    • ​参考答案​​:

      • ​原理​​:通过mmap内存映射共享内核空间,减少数据拷贝次数。

      • ​性能​​:Binder传输速度比Socket快3倍,适合高频调用(如系统服务)。

  2. ​10.Compose优势​

    • ​问题​​:对比Compose与XML布局的渲染性能差异,并说明声明式UI的核心思想。

    • ​参考答案​​:

      • ​性能​​:Compose跳过冗余measure/layout阶段,减少嵌套层级。

      • ​声明式​​:UI = f(State)(状态变化自动触发重组,无需手动更新View)。

10.进程间通信(IPC)

11.ANR产生原因​

  1. ​主线程耗时操作​

    • ​I/O阻塞​​:主线程执行文件读写、数据库操作或网络请求(Android 4.0+主线程网络请求直接抛异常)。

    • ​复杂计算​​:大数据处理、图像渲染等占用CPU时间过长。

    • ​锁竞争​​:主线程等待子线程释放锁(如死锁或同步锁阻塞)。

  2. ​组件超时​

    • ​BroadcastReceiver​​:onReceive()未在限定时间内完成(前台10秒/后台60秒)。

    • ​Service​​:生命周期方法(如onCreate())超时(前台20秒/后台200秒)。

    • ​Input事件​​:按键或触摸事件5秒内未响应。

  3. ​系统资源瓶颈​

    • ​内存不足​​:频繁GC或内存泄漏拖慢主线程。

    • ​CPU抢占​​:高负载时主线程无法获取CPU资源。

    • ​Binder调用阻塞​​:跨进程通信超时或系统服务响应延迟

 12.ANR产生原因​解决方案与优化策略​

  1. ​异步处理耗时任务​

  2. ​组件优化​

    • ​BroadcastReceiver​​:使用goAsync()+ 子线程处理耗时逻辑

    • ​Service​​:改用``或JobIntentService异步执行任务。

  3. ​资源与锁管理​

    • ​减少锁竞争​​:避免嵌套锁,使用ReentrantLock替代synchronized

    • ​数据库优化​​:批量操作使用事务,减少磁盘I/O

      ​UI与内存优化​

    • ​布局扁平化​​:用ConstraintLayout减少层级,避免过度绘制。

    • ​内存缓存​​:LruCache缓存图片等资源,减少重复加载

13.OOM产生的主要原因​

  1. ​内存泄漏(核心原因)​

    • ​静态引用持有短生命周期对象​​:静态变量(如单例)持有ActivityView的强引用,导致其无法被回收。

    • ​未注销监听器/广播​​:如未在onDestroy()中调用unregisterReceiver()或移除Handler消息。

    • ​资源未关闭​​:CursorInputStreamBitmap未调用recycle()或关闭流。

  2. ​大对象分配与资源处理不当​

    • ​Bitmap加载过大​​:高分辨率图片未经压缩直接加载,占用内存远超控件显示需求。

    • ​缓存策略不合理​​:LruCache或内存缓存设置过大,或未及时清理失效数据。

  3. ​频繁创建对象与内存碎片​

    • ​临时对象泛滥​​:循环中频繁创建对象(如字符串拼接),引发频繁GC导致卡顿甚至OOM。

    • ​栈内存溢出​​:深度递归或局部变量过多导致栈空间耗尽(默认线程栈仅1MB左右)。

  4. ​系统限制与进程模型​

    • ​内存配额限制​​:每个应用进程有固定上限(中低端设备32-64MB,高端设备192MB+),可通过ActivityManager.getMemoryClass()获取。

    • ​Native内存与Java堆分离​​:Bitmap通过Native分配内存,占用C层空间,但受总进程内存限制

14.OOM解决办法

根治内存泄漏​

​场景​

​解决方案​

静态引用Activity

改用Application ContextWeakReference

Handler/Runnable泄漏

使用静态内部类 + WeakReference,并在onDestroy()中移除消息。

单例模式

初始化时传入Application Context而非Activity Context

资源未关闭

finally块或try-with-resources中关闭流、回收Bitmap

2. Bitmap优化(核心场景)

​采样压缩​​:通过BitmapFactory.Options.inSampleSize按需缩放图片

  • 编码格式优化​​:使用Bitmap.Config.RGB_565(占内存为ARGB_8888的一半)

  • ​及时回收​​:非显示状态的Bitmap主动调用recycle()并置null

  • ​三级缓存策略​​:内存缓存(LruCache) + 磁盘缓存(DiskLruCache) + 网络加载,避免重复解码

 内存管理与编码规范​

  • ​对象复用​​:

    • ListView/RecyclerView使用ViewHolder+convertView复用视图。

    • 避免在onDraw()等高频方法中创建对象,减少内存抖动。

  • ​数据结构优化​​:

    • 递归算法改迭代,避免栈溢出。

    • 大对象分块加载(如分页读取文件)。

  • ​引用类型选择​​:

    • 缓存使用WeakHashMapSoftReference,允许GC在内存紧张时回收对象

15. Android 测量一个imageview的大小,在什么生命周期能测量到?

在 Activity的 onCreate()onStart()或 onResume()中直接调用 imageView.getWidth()或 imageView.getHeight()​通常返回 0​​,原因如下:

  • ​视图未完成布局​​:此时视图树仅完成初始化,但尚未经过测量(Measure)和布局(Layout)阶段。

  • ​布局流程未结束​​:Android 的视图布局分为三个阶段:

    1. ​Measure​​:计算视图大小(onMeasure())。

    2. ​Layout​​:确定视图位置(onLayout())。

    3. ​Draw​​:绘制视图内容(onDraw())。

    4. 只有完成 ​​Layout 阶段​​后,尺寸才被确定

    5. 可获取尺寸的生命周期及方法​ ​​onWindowFocusChanged():窗口焦点变化时,当 Activity窗口获得焦点(用户可见且可交互)时,视图已完成布局,此时可直接获取尺寸

16.Android jectpack有哪些组件,有哪些作用?

​一、Jetpack 的定义与价值​

​定位​​:Jetpack 是 Google 推出的​​标准化开发组件集合​​,旨在解决四大痛点:

  • ✅ ​​加速开发​​:减少样板代码(如数据库操作、生命周期处理)

  • ✅ ​​兼容性保障​​:自动适配不同 Android 版本(如 AppCompat实现 Material Design 兼容)

  • ✅ ​​架构规范​​:强制推行 MVVM 等现代化架构,提升可维护性

  • ✅ ​​性能优化​​:通过生命周期感知机制避免内存泄漏

💡 ​​面试点睛​​:可类比为“Android 开发的瑞士军刀”,整合了 iOS 的 CocoaPods + UIKit 功能


📦 ​​二、核心组件分类与作用​

⚙️ ​​1. 架构组件(Architecture)​

组件

核心作用

典型场景举例

​ViewModel​

管理 UI 相关数据,​​独立于 Activity/Fragment 生命周期​​(屏幕旋转不丢失数据)

保存页面状态(如用户输入表单)

​LiveData​

生命周期感知的​​数据观察者​​,自动更新 UI 并避免内存泄漏

实时展示数据库查询结果

​Room​

SQLite 的 ORM 抽象层,​​编译时校验 SQL 语句​

本地缓存用户数据(@Entity@DAO

​Navigation​

管理 Fragment 导航栈,​​可视化配置页面跳转关系​

实现单 Activity 多 Fragment 架构

​WorkManager​

​可靠的后台任务调度​​(支持设备重启后继续执行)

定期同步服务器数据

🎨 ​​2. UI 组件​

组件

核心作用

​Compose​

声明式 UI 工具包(未来趋势),​​实时预览​​布局

​RecyclerView​

高效加载大数据集列表(支持差异化更新)

​ConstraintLayout​

扁平化布局减少嵌套,优化渲染性能

​Paging​

分页加载大数据集(如聊天记录、商品列表)

⚡️ ​​3. 行为组件(Behavior)​

组件

核心作用

​CameraX​

标准化相机开发(兼容不同设备)

​DownloadManager​

系统级文件下载管理(断点续传、通知栏进度)

​Permissions​

简化运行时权限请求流程

🧱 ​​4. 基础组件(Foundation)​

组件

核心作用

​AppCompat​

向后兼容 Material Design 控件

​Android KTX​

Kotlin 扩展函数库(如简化 findViewById

​DataStore​

替代 SharedPreferences的安全数据存储


⚖️ ​​三、Jetpack 与传统开发对比​

维度

传统开发

Jetpack 开发

​代码量​

高(需手动处理生命周期)

减少 30%-50% 样板代码

1

​内存泄漏风险​

高(需谨慎管理引用)

低(LiveData/ViewModel 自动清理)

​测试便利性​

需大量 Mock 环境

内置 Test组件支持单元测试

17.Android 动画讲一下

回答:帧动画、补间动画(也称为视图动画或Tween动画)和属性动画

帧动画原理​​

通过顺序播放一组静态图片(每张图片为一帧)形成动态效果,类似传统幻灯片或电影播放

缺点​​:

  • ​内存占用高​​:大量或大尺寸图片易引发OOM(Out of Memory)。

  • ​灵活性低

补间动画

  1. ​原理​​:

    通过定义动画的​​起始状态​​和​​结束状态​​,系统自动计算中间帧(如平移、缩放、旋转、透明度变化)。​​仅改变View的显示效果,不改变实际属性​​(例如平移后点击事件仍在原位置)。

  2. ​类型与实现​​:

    • ​四种基本类型​​:

      • AlphaAnimation(透明度)

      • RotateAnimation(旋转)

      • ScaleAnimation(缩放)

      • TranslateAnimation(位移)

属性动画(Property Animation)​

  1. ​原理​​:

    ​动态修改对象的属性值​​(如View的坐标、透明度),真实改变属性,支持任意对象(不限于View)。

  2. ​核心类​​:

    • ValueAnimator:计算属性值变化,通过监听器更新视图。

    • ObjectAnimator:直接绑定对象属性(如 translationXalpha)。

    • AnimatorSet:组合多个动画(playTogether()playSequentially())。

  3. ​优势​​:

    • ​交互性​​:动画后点击事件随位置变化(例如平移按钮可在新位置响应点击)。

    • ​灵活性​​:支持自定义插值器(控制速度变化)和估值器(计算非数值属性)。

18.说一下Android中的设计模式

19.讲一下Android的架构

20.Android 为什么要用recyclevie代替listview

21.kotlin中的一下资料

22.Kotlin协程在实际项目中的最佳实践有哪些?

附:面试准备建议​

  1. ​基础巩固​​:

    • 必刷:Activity/Fragment生命周期、四大组件通信、Handler机制。

  2. ​进阶重点​​:

    • 深入View绘制/事件分发、内存优化、协程原理。

  3. ​架构设计​​:

    • 准备1-2个模块化/MVVM项目案例,说明技术选型原因。

  4. ​工具使用​​:

    • 熟练使用Profiler、LeakCanary、Systrace定位问题

### Android 测试面试常见问题及标准答案 #### 1. 解释一下 UI Automator Viewer 的作用是什么? UI Automator Viewer 是一种工具,用于捕获和分析 Android 设备屏幕上的用户界面 (UI) 层次结构。通过该工具可以方便地查看应用中的视图层次以及各个控件的属性,这有助于编写更精确的自动化测试脚本[^2]。 ```bash adb shell uiautomator dump /sdcard/window_dump.xml uiautomatorviewer ``` #### 2. 如何理解 Android 中的 Instrumentation 和 JUnit? JUnit 是 Java 编程语言中广泛使用的单元测试框架之一,在 Android 开发环境中同样适用;而 Instrumentation 提供了一种机制使得应用程序可以在受控条件下运行并收集有关其行为的信息。两者结合起来能够实现对 Android 应用的有效功能验证。 #### 3. 描述下如何创建一个简单的 Espresso 测试案例? Espresso 是 Google 推荐的一个用于简化 Android 应用交互操作记录过程的强大库。要构建基本的功能性测试: - 添加依赖项到项目的 build.gradle 文件; - 使用 `@RunWith(AndroidJUnit4::class)` 注解类级别; - 运用 onView() 方法定位目标组件; - 调用 perform() 执行动作如点击或输入文字; - 断言预期结果是否满足条件。 ```kotlin import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule import org.junit.Rule import org.junit.Test class ExampleTest { @get:Rule val activityRule = ActivityScenarioRule(MainActivity::class.java) @Test fun testButtonFunctionality() { // Click on a button with id R.id.my_button and check if text changes to expected value. onView(withId(R.id.my_button)).perform(click()) onView(withText("Expected Text")).check(matches(isDisplayed())) } } ``` #### 4. 在资源有限的情况下怎么保障产品质量? 即使面临项目进度紧迫、团队规模较小等问题时也应坚持核心原则——确保交付可用的产品版本。具体措施包括但不限于:优化现有流程减少浪费时间的任务;优先处理高风险区域内的缺陷修复工作;鼓励跨职能协作提高效率;利用持续集成/部署平台加快反馈循环速度;适当调整发布周期以适应实际情况变化等[^4]。 #### 5. 测试计划应该包含哪些要素? 一份完整的测试计划应当涵盖以下几个方面:明确测试的目标与范围;制定详细的执行方案说明采用何种方法论来进行评估活动;规划所需的人力物力支持情况;搭建合适的实验场地模拟真实应用场景;合理安排日程表以便跟踪进展状况。此外还需考虑特殊场景下的应急响应预案准备[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值