Application startup classification

Cold start

The user clicks the app icon on the screen and goes through the process of showing the startup window, creating the process, and showing the app

Warm start

The user process is already created and needs to be reinitialized if it responds to a low-memory event, such as clearing resources in onTrimMemory

How do I check the startup duration of an application

  • throughadb shell am start -S -W $packageName/.MainActivityStart the test
  • Call by displayreportFullDrawnBased on service requirements, the system is notified to complete the loading
  • throughandroid-sdk/platform-tools/systracesystrace.pythroughPython systrace.py --time=10 -o launch.html sched gfx view wmLook at the time taken for each function
  • throughAndroid Studio ProfilerStart the Application view

Why is there a blank screen

During application startup, ActivityStack’s startActivityLocked method determines the startup mode of the application. If the startup mode is cold, Call the ActivityRecord windowContainerController showStartingWindow method, add the white pages

A PhoneWindow is created and added to the window by calling the addSplashScreen method of mPolicy through WindowMangerService

The key code

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);Copy the code

How to optimize

Enable optimization step classification

  • Visual optimization of white screen
  • MultiDexTo optimize the
  • Logical code optimization
  • Home page layout optimization

White screen optimization

For the optimization of the white screen startup page, according to the above code analysis, you can set the theme, add a picture consistent with the launch page for windowBackground, and visually deceive the user

MultiDex optimization

As the application continues to iterate, the number of internal methods will continue to increase, eventually exceeding the maximum number of methods. And the authorities have also withdrawn from the MultiDex solution, which means subcontracting. On lower versions of mobile DVM, we need to manually call multidex. install to load files other than the main Dex, which may cause ANR.

Optimization of lower version startup

Faced with this problem, we can adopt the solution proposed by Facebook. Create a new process and call multidex.install in the attachBaseContext of the Application. The main process can block until the loading is complete by several means before entering the Application

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() } } }Copy the code
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() {// Cannot exit}  companion object { private const val TAG = "MultiInstallActivity" } }Copy the code
<activity
    android:name="com.weex.multidexinstall.MultiInstallActivity"
    android:launchMode="singleTask"
    android:process=":install" />
Copy the code

Logical code optimization

During the startup process of the Application, we usually load the SDK in onCreate of the Application and read the value in the SharedPreference

  • forSharedPreferenceCan be replaced byMMKV
  • For other business logic loads, you can refer to Alpha to build your own asynchronous startup framework

Home page layout optimization

For layout optimization, some common techniques are as follows

  • ViewStub
  • mergeThe label
  • useConstraintLayoutReplace the original layout label