应用启动分类
冷启动
用户点击屏幕上的应用图标,经过展示启动窗口
、创建进程
、展示应用
几个过程
热启动
用户进程已经创建,如果响应了低内存事件,例如在 onTrimMemory
中清除资源,则需要重新初始化
如何检测应用启动时长
- 通过
adb shell am start -S -W $packageName/.MainActivity
启动检测 - 通过显示调用
reportFullDrawn
根据业务需求,通知系统完成加载 - 通过
android-sdk/platform-tools/systrace
下systrace.py
通过Python systrace.py --time=10 -o launch.html sched gfx view wm
查看每个函数的耗时 - 通过
Android Studio Profiler
启动应用查看
为什么会出现白屏
在应用启动过程中 ActivityStack
的 startActivityLocked
方法中会判断当前应用的启动模式,若为冷启动,则调用 ActivityRecord
中 windowContainerController
的 showStartingWindow
方法,添加启动白屏页
通过 WindowMangerService
调用 mPolicy
的 addSplashScreen
方法,创建了一个 PhoneWindow
添加到窗口上
关键代码
if (theme != context.getThemeResId() || labelRes != 0) { try { context = context.createPackageContext(packageName, CONTEXT_RESTRICTED); context.setTheme(theme); } catch (PackageManager.NameNotFoundException e) { // Ignore } } final PhoneWindow win = new PhoneWindow(context); win.setIsStartingWindow(true); win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); view = win.getDecorView(); if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for " + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null)); wm.addView(view, params);
如何优化
启动优化步骤分类
- 白屏的视觉优化
-
MultiDex
优化 - 逻辑代码优化
- 首页布局优化
白屏的优化
对于白屏启动页面的优化,根据上述的代码分析,可以通过设置主题,为 windowBackground
添加与启动页一致的图片,视觉上可以骗过用户
MultiDex 优化
着应用的不断迭代,内部的方法数会不断增加,最终超过方法数上限。而官方也退出了 MultiDex
的方案来解决,也就是意味着分包。在低版本手机 DVM 上,我们需要手动调用 MultiDex.install
加载主 Dex
以外的文件,可能造成 ANR
。
低版本启动的优化
面对这个问题,我们可以采用 Facebook 提出的方案。创建一个新的进程在 Application
的 attachBaseContext
中调用 MultiDex.install
,主进程可以通过多种手段阻塞等到加载结束之后再进入应用
class App : Application() { override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (isAsyncLaunchProcess().not()) { val thread = DexInstallDeamonThread(base) thread.start() synchronized(lock) { try { lock.wait() } catch (e: InterruptedException) { e.printStackTrace() } } thread.exit() } } fun isAsyncLaunchProcess(): Boolean { val processName = SystemUtils.getCurrentProcessName(this) return processName != null && processName.contains(":install") } private class DexInstallDeamonThread(private val base: Context) : Thread() { private var handler: Handler? = null private var looper: Looper? = null @SuppressLint("HandlerLeak") override fun run() { Looper.prepare() looper = Looper.myLooper() handler = object : Handler() { override fun handleMessage(msg: Message) { synchronized(lock) { lock.notify() } } } val messenger = Messenger(handler) val intent = Intent(base, MultiInstallActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.putExtra("MESSENGER", messenger) base.startActivity(intent) Looper.loop() } fun exit() { if (looper != null) looper!!.quit() } } }
class MultiInstallActivity : AppCompatActivity() { private var messenger: Messenger? = null public override fun onCreate(savedInstanceState: Bundle?) { requestWindowFeature(Window.FEATURE_NO_TITLE) super.onCreate(savedInstanceState) window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN) setContentView(R.layout.activity_install) val from = intent messenger = from.getParcelableExtra("MESSENGER") thread { try { Log.d(TAG, "start install") MultiDex.install(application) Thread.sleep(5000L) Log.d(TAG, "finish install") messenger?.send(Message.obtain()) } catch (e: Exception) { e.printStackTrace() } runOnUiThread { finish() exitProcess(0) } } } override fun onBackPressed() { //无法退出 } companion object { private const val TAG = "MultiInstallActivity" } }
<activity android:name="com.weex.multidexinstall.MultiInstallActivity" android:launchMode="singleTask" android:process=":install" />
逻辑代码优化
在应用启动过程中,我们一般会在 Application
的 onCreate
中加载 SDK
以及读取 SharedPreference
中的值等耗时操作
- 对于
SharedPreference
可以替换为MMKV
首页布局优化
对于布局优化,比较常见的一些技术如
ViewStub
-
merge
标签 - 使用
ConstraintLayout
替换原来的布局标签
相关教程
Android基础系列教程:
Android基础课程UI-布局_哔哩哔哩_bilibili
Android基础课程UI-控件_哔哩哔哩_bilibili
Android基础课程UI-动画_哔哩哔哩_bilibili
Android基础课程-activity的使用_哔哩哔哩_bilibili
Android基础课程-Fragment使用方法_哔哩哔哩_bilibili
Android基础课程-热修复/热更新技术原理_哔哩哔哩_bilibili
本文转自 https://juejin.cn/post/7054214019749511205,如有侵权,请联系删除。