首页 最新 热门 推荐

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

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

  • 25-04-16 15:21
  • 4789
  • 9503
juejin.cn

一、说说 ContentProvider 的初始化顺序?

在Android应用启动过程中,ContentProvider的初始化顺序是由系统控制的,而开发者对其影响有限。 

通常,ContentProvider是在应用进程启动时,由Android框架在Application的onCreate方法之前初始化的,主要原因是ContentProvider可能会在应用的其他组件创建之前需要被访问(比如系统为了满足跨进程通信或数据存取的需要)。

1.1 Provider 的启动顺序

系统预加载:

系统级ContentProvider,如:Contacts、Media相关的提供者,会在设备启动或用户登录时由系统初始化。 

应用内部的ContentProvider: 

  • 声明顺序: 在AndroidManifest.xml中声明的ContentProvider其初始化顺序遵循该文件中的声明顺序。Android会按照Manifest中次序初始化ContentProvider。
  • 优先级原则: 不同应用间没有明确的提供者加载顺序,但同一个应用内部是遵循Manifest文件中的书写顺序。

1.2 影响启动顺序的因素

  • Manifest 优先级: 虽然按Manifest中的顺序初始化,但无法保证在所有不同设备和操作系统版本下都能严格遵循这一定义。
  • 初始化依赖: 若某个ContentProvider依赖于另一个提供者,显式地控制初始化顺序则会变得更复杂。
  • 多进程情况: 如果不同的ContentProvider在不同的进程中运行,进程的启动时间可能对它们的初始化顺序有影响,这和进程管理的复杂有关。

1.3 如何自定义ContentProvider并影响启动顺序

虽然开发者不能完全控制启动顺序,但可以通过以下几种做法稍微管理ContentProvider的加载顺序: 

  • 慎重设计依赖: 避免在ContentProvider中依赖其他尚未初始化的提供者。 
  • 手动依赖管理: 在可能的情况下,将依赖逻辑放在另一个启动后加载的组件中如Activity或Service中,以延迟加载具体功能。 
  • 避免复杂的初始化逻辑: 在ContentProvider的onCreate方法中尽量避免复杂的逻辑,保持轻量级,这样即便初始化顺序无法预知也不会造成大的性能或逻辑问题。 
  • 使用静态代码块: 可选择在ContentProvider外部使用静态代码块或独立的初始化方法来提升必要资源的准备。

二、如何优化Android应用的启动时间?

2.1 冷启动优化

冷启动是指应用从完全关闭状态启动的过程。优化冷启动时间的关键在于减少启动时加载的资源量和初始化操作的耗时。

  • 可通过将非关键组件的初始化操作延迟到应用启动后执行,可以减少冷启动时间。

示例代码:

Kotlin
代码解读
复制代码
class MyApplication:Application(){     override fun onCreate(){         super.onCreate()         // 延迟初始化非关键组件         Handler().postDelayed({             initNonCriticalComponents()         },1000)     }     private fun initNonCriticalComponents(){         // 初始化非关键组件     } }

2.2 热启动优化

热启动是指应用从后台恢复的过程。优化热启动时间的关键在于合理管理应用的生命周期,避免不必要的资源重新加载。

  • 可通过缓存数据,避免在热启动时重新加载数据,可以显著提升热启动速度。

示例代码:

Kotlin
代码解读
复制代码
class MainActivity:AppCompatActivity(){     private lateinit var cachedData:List     override fun onCreate(savedInstanceState:Bundle?){         super.onCreate(savedInstanceState)         if(savedInstanceState !=null){             // 从缓存中恢复数据             cachedData =  savedInstanceState.getStringArrayList("cachedData") as List         }else{             // 加载新数据             cachedData =loadData()         }     }     private fun loadData():List{         // 加载数据         returnlistOf("Data1","Data2","Data3")     }     override fun onSaveInstanceState(outState:Bundle){         super.onSaveInstanceState(outState)         outState.putStringArrayList("cachedData",ArrayList(cachedData))     } }

2.3 使用启动框架管理启动任务

使用启动框架可以将核心业务提前加载完成,同时将任务细粒度化。例如,为了使首页更快地展示,可以将首页的数据请求和UI渲染相剥离。

  • 可通过任务分发器管理启动任务,可以优化启动流程,减少启动耗时。

示例代码:

Kotlin
代码解读
复制代码
class MyApplication:Application(){     override fun onCreate(){         super.onCreate()         // 初始化启动任务分发器         TaskDispatcher.init(this)         val dispatcher:TaskDispatcher=TaskDispatcher.createInstance()         // 添加任务并启动         dispatcher.addTask(InitSumHelperTask(this))                 .addTask(InitMmkvTask())                 .addTask(InitAppManagerTask())                 .addTask(InitArouterTask())                 .start()         // 等待需要等待的任务执行完成         dispatcher.await()     } }

2.4 延迟加载非关键任务

将非关键任务延迟加载可以减少启动时的初始化工作,提升启动速度。

  • 可通过延迟加载非关键任务,可以避免在启动时执行不必要的操作,提升启动速度。

示例代码:

Kotlin
代码解读
复制代码
homeAdAdapter.onFirstFrameTimeCall = {     AppExecutors.mainThread.executeDelay(Runnable {         // 任务延迟3s执行         initToastTask()     }, 3000) }

2.5 使用启动引导页

在应用启动时显示一个启动引导页,同时异步加载应用资源,可以提升用户感知的启动速度。

  • 可通过设置启动引导页,可以掩盖启动时的空白时间,提升用户体验。

示例代码:

xml
代码解读
复制代码
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">     <item name="android:windowBackground">@drawable/splash_backgrounditem> style>

2.6 优化onCreate方法

避免在Activity的onCreate方法中执行耗时操作,使用HandlerThread或协程来异步处理耗时任务。

  • 可通过将耗时操作移至后台线程执行,可以避免阻塞主线程,提升启动速度。

示例代码:

Kotlin
代码解读
复制代码
class HomeActivity:AppCompatActivity(){     override fun onCreate(savedInstanceState:Bundle?){         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_home)         // 异步加载数据         val handlerThread =HandlerThread("DataHandlerThread")         handlerThread.start()         val handler =Handler(handlerThread.looper)         handler.post {             // 执行耗时操作             val data =loadData()             // 回到主线程更新UI             runOnUiThread {                 textView.text = data             }         }     }     private fun loadData():String{         // 模拟耗时操作         Thread.sleep(2000)         return"加载完成"     } }

2.7 性能监控与测试工具

  • Profiler: 用于监控应用的CPU、内存和网络使用情况,帮助开发者识别性能瓶颈。
  • TraceView: 用于分析应用的执行流程,找出耗时操作。
  • Systrace: 用于系统级的性能分析,帮助开发者优化系统启动过程。

三、性能优化篇:Framework层调优实战

3.1 如何定位Native层内存泄漏?

阿里方案:

  • 使用libmemunreachable检测不可达内存
  • AddressSanitizer实时监控(性能损耗<2%)
adb
代码解读
复制代码
检测命令  adb shell am dumpheap -n /data/local/tmp/heap.txt

3.2 View绘制优化方案

字节方案:

  • 使用RenderThread异步绘制(Android 12+)
  • 硬件加速策略动态切换

示例代码:

java
代码解读
复制代码
public class CustomView extends View {   private final ThreadedRenderer mRenderer;     void draw(Canvas canvas) {     if (mUseHardwareAccel) {       mRenderer.draw(canvas); // 硬件加速路径      } else {       super.draw(canvas); // 软件绘制      }   } }

3.3 如何将冷启动时间从4秒压缩到800ms?

可优化点如下:

  • ContentProvider治理:合并初始化逻辑,平均每个CP可节省80ms
  • 类加载优化:使用App Bundles动态交付非必要模块
  • IO异步化:如将SharedPreferences替换为MMKV,提高读写性能
  • 布局预加载:使用ViewStub + Merge 标签减少层级嵌套
  • 启动阶段监控:集成Firebase Performance Monitoring实现自动化埋点

四、组件启动篇:Activity启动全链路

4.1 Activity启动的跨进程调用

标准答案:

  • 冷启动:至少4次跨进程调用(含Zygote进程fork)
  • 热启动:2次跨进程调用(AMS -> ApplicationThread)

流程拆解示例:

log
代码解读
复制代码
Client->>AMS: startActivity()   AMS->>Zygote: fork进程    Zygote->>AMS: 返回新进程PID    AMS->>ApplicationThread: scheduleLaunchActivity()   ApplicationThread->>ActivityThread: handleLaunchActivity()

4.2 为什么会有"白屏问题"?

底层原理:

  • WindowManagerService在attach()阶段同步创建窗口
  • 主题背景绘制早于onCreate()执行

优化方案:

  • 使用SplashScreen API(API 31+)
  • 异步加载布局(ViewStub方案)

示例代码:

java
代码解读
复制代码
// 异步加载核心代码  public void onCreate(Bundle savedState) {   super.onCreate(savedState);   ViewStub stub = findViewById(R.id.async_stub);   stub.setInflateListener((stub, inflated) -> {     // 主线程空闲时执行    }); }

更多分享

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

/ 登录

评论记录:

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

分类栏目

后端 (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