首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Android 互联网大厂,高频重点面试题集分享(一)

  • 25-04-16 15:20
  • 2492
  • 6141
juejin.cn

一、Handler机制

1.1 Looper.loop()为什么不会阻塞主线程?

原理: 通过epoll_wait实现消息队列的空闲等待,配合Native层唤醒机制实现高效调度

本质解析:

  • 事件驱动模型:Native层的epoll_wait机制
  • 同步屏障:MessageQueue#postSyncBarrier()

关键源码路径以及代码示例:

java
代码解读
复制代码
// MessageQueue.next()   nativePollOnce(ptr, nextPollTimeoutMillis);   // Native层通过epoll监听文件描述符事件 // 同步屏障核心逻辑  public int postSyncBarrier() {   Message msg = Message.obtain();   msg.when = SystemClock.uptimeMillis();   msg.setAsynchronous(true);   return enqueueMessage(queue, msg, uptimeMillis); }

1.2 子线程创建Handler为什么会崩溃?

根本原因: 未初始化当前线程的Looper(需先执行Looper.prepare())

解决方案: 使用HandlerThread自动管理Looper生命周期。

1.3 如何实现消息优先级?

腾讯方案:

  • 自定义MessageQueue的enqueueMessage()
  • 使用红黑树代替链表(消息量>1000时效率提升30%)

代码示例:

java
代码解读
复制代码
void enqueueMessage(Message msg, long when) { if (mMessages == null || when < mMessages.when) {     msg.next = mMessages;     mMessages = msg;   } else {     Messageprev= mMessages;     Messagecur= prev.next;     while (cur != null && cur.when <= when) {       prev = cur;       cur = cur.next;     }     prev.next = msg;     msg.next = cur;   } }

二、Binder机制

2.1 Binder相比Socket的优势?

  • 内存映射技术(mmap)减少数据拷贝次数
  • 引用计数机制实现自动资源回收

2.2 AIDL生成Java类的工作原理?

  • 自动生成Stub(服务端)和Proxy(客户端)类
  • 数据序列化通过Parcel实现,关键代码如下:
java
代码解读
复制代码
// Book.aidl自动生成的方法   public void readFromParcel(Parcel parcel) {       this.name = parcel.readString();   }

2.3 Binder线程池管理?

  • 默认最大线程数16(可通过Process.setThreadPriority()调整)
  • 使用IPCThreadState维护线程状态

2.4 为什么Zygote不用Binder?

  • 安全性考量:Socket支持SELinux策略(SEAndroid)的精细控制。
  • 效率对比:fork进程时Socket通信耗时比Binder少。
  • 生命周期:Zygote进程存活周期与SystemServer解耦。

2.5 Binder数据量传输极限?

技术本质:

  • 内核限制:mmap内存映射区大小(默认1M-8K)
  • 协议限制:Binder事务缓冲区大小(通过BINDER_SET_MAX_THREADS设置)

避坑指南:

  • 跨进程传递Bitmap时使用Ashmem(实测2MB图片传输速度提升4倍)
  • 大文件传输改用Socket+ContentProvider方案(微信方案)

三、Jetpack架构组件

3.1 ViewModel配置变更后为什么能存活?

  • 通过HolderFragment+NonConfigurationInstances机制保留引用
  • 源码关键类:ViewModelStoreOwner

3.2 LiveData防止内存泄漏的原理?

  • 基于Lifecycle的ON_DESTROY事件自动移除观察者

核心代码:

java
代码解读
复制代码
// LifecycleBoundObserver.onStateChanged()   if (state == DESTROYED) {       removeObserver(mObserver);   }

四、Kotlin协程挂起函数的线程调度

4.1 协程上下文切换原理

  • Dispatchers.IO实际使用LimitingDispatcher控制并发量
  • 与线程池关系:共享DefaultScheduler底层线程池

4.2 挂起函数状态机如何实现的?

  • 编译器生成ContinuationImpl子类管理执行状态

反编译后关键代码:

kotlin
代码解读
复制代码
// 编译后的挂起函数   label = when (this.label) {       0 -> { /* 初始状态处理 */ }       1 -> { /* 恢复点处理 */ }   }

五、性能优化之内存抖动检测和ANR分析实战

5.1 内存抖动如何定位?

  • 使用Allocation Tracker抓取连续内存分配
  • 典型案例:避免在onDraw()中创建对象

5.2 ANR日志解读?

  • 分析/data/anr/traces.txt中的堆栈信息
  • 重点关注Binder调用阻塞(如ContentProvider操作)

六、Flutter混合开发中通信(Platform Channel)原理相关

6.1 Dart与Native通信性能瓶颈?

  • MethodChannel使用二进制序列化(优于JSON)
  • 大数据传输推荐BasicMessageChannel

6.2 线程模型陷阱?

  • Android端回调默认在 UI线程 执行,耗时操作需切换线程

关键代码:

java
代码解读
复制代码
// 在子线程执行耗时操作   new Handler(Looper.getMainLooper()).post(() -> {       result.success(data);   });

七、情景案例题分析及解答

7.1 场景一:

某头部电商APP启动时出现持续3秒的黑屏/白屏,技术方案评审会上出现两派争论:

  • 客户端组认为服务端接口响应慢
  • 服务端组指责客户端冗余初始化任务太多

面试时可能忽略的细节:

  1. ContentProvider初始化耗时(平均每个CP增加80ms)
  2. MultiDex加载时间在Android 5.0以下设备呈指数级增长
  3. 经典误区: 盲目使用IntentService预加载数据,反而加剧CPU竞争

冷启动优化方案:

优化阶段传统方案进阶方案
任务调度异步初始化基于Startup库的拓扑排序
页面渲染减少层级使用ConstraintLayout布局,减少绘制时间
IO 优化合并SP文件迁移到MMKV提升读写性能
监控体系手动打点字节码插桩+火焰图定位瓶颈

7.2 场景二:

某千万级DAU的IM软件,消息列表在快速滑动时出现明显卡顿,即使使用RecyclerView + ViewHolder模式仍无法解决。

常见回答:

  • 布局绘制:仅关注LinearLayout层级,未发现Canvas.saveLayer()导致的离屏渲染
  • 内存抖动:在onBindViewHolder中频繁创建SimpleDateFormat实例
  • 线程管理:在滑动过程中触发网络请求,造成MainLooper阻塞

性能调优组合拳:

渲染层优化:

xml
代码解读
复制代码
<ImageView android:src="@drawable/msg_bg" /> <View android:background="@color/msg_bg_color" /> 

内存治理三板斧:

  • 采用PoolingObjectPool复用MessageItem对象
  • 使用StrictMode检测主线程IO操作
  • 通过LeakCanary监控ViewHolder泄漏

滑动优化:

java
代码解读
复制代码
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {       override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {             when (newState) {                  SCROLL_STATE_DRAGGING -> pauseImageLoading() // 滑动时暂停图片加载                              SCROLL_STATE_IDLE -> resumeImageLoading()                  }          } })

7.3 场景三:

某音视频社交APP在直播连麦场景下,当观众数超过500人时,主播端出现帧率从60FPS暴跌至15FPS的现象。候选人需要定位性能瓶颈并提供优化方案。

错误回答和容易忽略的细节:

  • 锁定GPU过度绘制,却忽略了三重关键指标(CPU线程调度、内存抖动、I/O阻塞)
  • 暴力解法:建议禁用动画/降低分辨率(破坏核心用户体验)
  • 测试盲区:无法复现线下测试场景与线上真实设备差异

优化方案:

分层排查法:

  • 使用Android GPU Inspector抓取渲染管线数据
  • 结合Systrace分析主线程阻塞点(如Choreographer#doFrame耗时)
  • 通过Memory Profiler检测ByteBuffer内存抖动

代码改造示例:

java
代码解读
复制代码
// 优化前:同步解码+渲染 mVideoDecoder.decodeFrame(buffer); mSurfaceView.renderFrame(frame); // 优化后:异步双缓冲队列 ExecutorService decoderExecutor = Executors.newSingleThreadExecutor(); // 防止OOM BlockingQueue frameQueue = new ArrayBlockingQueue<>(2);

接入大厂开源SDK(终极武器):

接入字节跳动开源的直播性能监控SDK ,实现帧率、卡顿率、CPU占用率的三维实时埋点

更多分享

  1. Android 互联网大厂,高频重点面试题集分享(二)
  2. Android 常规基础面试题分享
  3. Android Kotlin协程相关面试题分享
  4. Android 架构以及优化相关面试题分享
注:本文转载自juejin.cn的QING618的文章"https://juejin.cn/post/7472344367539830819"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top