preface

Recently, a problem has been raised in the department. The application starts slowly and the icon is blocked. Mainly in low-end models. To investigate this problem, because of the performance optimization is more interested, borrow a low-end machine and a mid-end machine to have a look, the same application respectively measured its startup time in the low-end machine, the following is the startup time:

It started three times, mostly around 4s.

why

The main reason is that tasks are too centralized before interface drawing.

From the moment the user clicks the launcher icon to the moment he sees the first frame, the application launches through the following steps:

main()->Application:attachBaseContext()->onCreate()->Activity:onCreate()->onStart()->onPostCreate()->onResume()->onPostR esume()

The initialization task is usually centralized in the Application:onCreate() method, which causes the initialization task to be completed before the first frame is drawn, which causes the card icon and the Application to start slowly. What about breaking things up? Scatter in LaunchActivity to fragment initialization? This doesn’t work because the interface starts drawing after the onResume() method starts, so you have to look at the Activity creation process.

The main->Activity creation process will go through a series of framework layer operations, which are automatically performed by the system and are not easy to optimize, but you can find some clues before and after the Activity creation process. Because the Activity will always to create ActivityThread: performLaunchActivity () this method, in this way can know a few things:

1, first through Instrumentation: newActivity () to create an Activity instance

2. Check whether the Application instance has been created

Instrumentation: newApplication () to create the Application instance, in the process can be carried in turn attachBaseContext () and the onCreate () method

3. After that, the Activity: Attach () method creates a PhoneWindow object, which is the interface. It has a DecorView, which is configured when setContentView() is called.

Our View is also added to the DecorView. It must be displayed first as a RootView, so we can give it a default background

measures

1. Task classification 2. Task parallelism 3

For the task set initialization and time-consuming initialization causes that the application starts too slowly on mid – and low-end computers, and simply assigning tasks to the Activity initialization does not work due to the timing of the Activity interface drawing, we must find a starting point

The first is the Application attachBaseConte and onCreate methods, and the second is the Application creation until the interface is drawn

So, the critical points at which tasks can be graded can be classified as follows:

HighPrioritySDK — Activity creation 3 LowPrioritySDK — Activity interface drawing 4 AsyncSDK — Activity creation

As shown in figure:

After grading tasks like this and testing them, the app starts in seconds, even on low-end machines:

Problems with grading

Normal startup process is certainly fine, but there are several scenarios:

2. When the Application is not suspended, Push Push needs to jump to an interface in the Application from Notification. 3. The browser link needs to jump into an in-app interface

These cases may lead to the problem that the interface jumped into uses the uninitialized SDK, which may lead to Crash or abnormal data, so the SDK must be initialized before the target page is started. The reason for this process is that the startup page is not aroused to initialize the SDK, which can be solved by hook newActivity. It determines whether the Application is initialized and each SDK is initialized, and whether the startup is not from the system Launcher.

public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { if (InitializeOptimizer.isApplicationCreated() && (! InitializeOptimizer.isHighSDKInitialized() || ! InitializeOptimizer.isLowSDKInitialized() || ! InitializeOptimizer.isAsyncSDKInitialized()) && ! InitializeUtil.isAppLauncher(intent)) { InitializeOptimizer.setApplicationCreated(false); intent.addCategory(InitializeUtil.INITIALIZE_CATEGORY); return (Activity) cl.loadClass(WDInitializeOptimizer.getLaunchClassName()).newInstance(); } InitializeOptimizer.setApplicationCreated(false); return super.newActivity(cl, className, intent); }Copy the code