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
- through
adb shell am start -S -W $packageName/.MainActivity
Start the test - Call by display
reportFullDrawn
Based on service requirements, the system is notified to complete the loading - through
android-sdk/platform-tools/systrace
下systrace.py
throughPython systrace.py --time=10 -o launch.html sched gfx view wm
Look at the time taken for each function - through
Android Studio Profiler
Start 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
MultiDex
To 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
- for
SharedPreference
Can 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
merge
The label- use
ConstraintLayout
Replace the original layout label