background

Recently, in the process of development, I found that every time I clicked the APP to start from the desktop, there was an obvious waiting time on the desktop. The lower-end model was more obvious, and the optimization of cold start seemed to be imperative, so I angrily studied and then solved it. Before and after optimization:

Buyers show (GIF) :

Taobao Show (GIF) :

Android App startup process:

As the saying goes, if you want to optimize, the process can not be little! The flow chart of android app startup is as follows:

To summarize a completed cold start app process should go through:

Zygote Fork Proccess 
-> Application:attachBaseContext()
-> Application:onCreate() 
-> MainActiviity:onCreate()Copy the code

The main point here is to write out the corresponding life cycle callback. Because most of your business code is called in these function callbacks.

Optimization points related to App cold start

1. Reduce time-consuming operations within the life cycle:

Application: attachBaseContext () :

The general minefield in this method is mainly in this code, because under Android 5.0 (API 21) there will be a problem of 65535 method subcontract, when dex is too large, it will lead to Application start slowly, ANR or ClassNotFound and other exceptions, Subcontracting solutions and optimization solutions on the web will not be described.

Application: the onCreate ()

This method needs to be optimized, because the third party plug-in initialization is usually placed here, doing heavy things in the Application initialization will seriously block the app startup (DiskIO, network request, etc.). The following is the initialization time of our third-party plug-in:

The debug:

Release:

Debug and release time are posted here, hope you do not repeat the same mistake… Because in debug mode and release mode, one is about 1000ms, and the other is about 300ms, the error is very large, please be sure to test the data under release !!!!

The solutions to solve the initialization time of third-party plug-ins are as follows: 1. SDKS are loaded in priority, and non-necessary SDKS are implemented by lazy loading. 2. SDKS that can be initialized by multiple threads are initialized by multiple threads.

MainActiviity: onCreate ()

Again, try not to do time-consuming operations or render overly complex layouts in this layout. When I analyzed my app, I found a line of code in onCreate:

Its function is to ensure that the user can see Splash’s picture when opening it, and the loading is actively delayed for 1s. A better solution would be to put the jump to MainPage in onResume instead of onCreate. In Android system, onResume must be visible and interactive, and users must be able to see SplashActivity before jumping. This is determined by the system life cycle, instead of waiting for a fixed 1s. After optimization, the startup speed is increased by 500ms. Therefore, it is suggested that we follow the life cycle to do some things in the future, and try not to artificially delay blocking.

2. Avoid cold startup

There are generally three startup modes of App:

· ColdStart — ColdStart:

This is the most time consuming, usually because the process is dead and the system needs to re-fork the process for a series of initializations.

· WarmStart — WarmStart

It is a little faster than ColdStart, because all Activities of the app are still in memory and are not killed. All you do is to bring the app from the background to the foreground. There is no need to reinitialize a series of behaviors, which reduces the work of object initialization and layout loading. But it behaves like a cold boot, with displays a blank screen until the App renders the activity. This blank screen will be explained later.

· LukeWarm Start — hot Start

The fastest startup mode, similar to the back key exit application and immediately enter the kind of behavior.

Optimization scheme:

Since the cold start is so slow, we do not quit the process when the user does not kill the process or when the system tells the process to do so. Hook the back button in the Activity at the bottom of the Activity stack to ensure that the user does not exit the app after clicking the back button. At the bottom of our stack in our App must be our MainActivity, because all system behavior is derived from it. So just add the following:

MoveTaskToBack: Instead of finishing the Activity, it simply hides it in the background. Similar to the effect of the user actively triggering the system Home button. The comparison before and after the optimization is as follows:

Before optimization (GIF) :

After optimization (GIF) :

As shown in Figure 1, the optimization effect will be more obvious after process recycling after a long time.

3.WindowBackGround — Remove the last layer of thin stockings

After the above operation, I found that there is no use!! The startup speed is improved, but the App still pauses on the desktop when clicked. Wow ~ very uncomfortable ~ on second thought, an APP launch is always a new Fork process, is this the problem that causes it to pause on the desktop for a while? How do other apps do it in seconds? There is a sentence in the launch-time Performance of AndroidDeveloper:

When you create an App process, the Android system will immediately display a background window for you, and then create the App process. When the App completes first Draw, it will be replaced by your MainActivity (that is, the default Activity). The background window is the blank screen mentioned in WarmStart. Here’s the answer to the riddle. The so-called second opening turns out to be visual deception… So for someone to tell you that they’re just trying to optimize the lifetime of the initialization code to a second is bullshit. However, I have to admit that the user experience is greatly improved. As soon as the user clicks on the launcher, a background image is rendered, giving the user a feeling that it has been started. A series of optimizations made in the previous work are aimed at making the user look less at the black Window rendered by the system for a while.

So why does our APP appear on the system desktop for a while instead of rendering the background image? LauncherActivity creates a LightTheme for launcherActivity by default. This will cause the App to display its Activity in a white screen for a period of time. To solve the problem, change the theme to transparent as shown below

In fact, although this solves the problem of the white screen, it will appear as mentioned above. Click and stay on the desktop for a while until MainActivity renders. That’s what most apps do, but it’s not the best solution.

WindowBackground best solution:

WindowBackground should be used as your brand promotion page or logo page. If your SplashActivity doesn’t need any initialization at all and just wants a splash screen, windowBackground can be used to do that.

1. Set a custom Theme with windowBackground

The first two lines of code make the Theme opaque and the default rendered background is the image of our must-see movie splash screen.

  • WindowBackground: Key, mainly set the background you want or dynamically draw the drawable line, this view will be rendered to the user when you cold boot.

  • WindowFullscreen: Display in full screen, so that the top status bar does not show inconsistent colors that are too disjointed and abrupt

2. Set your launcher Theme for your Activity

3. Set the theme back to your own AppTheme after Launch Activity

At this point, your App can complete the second to open!

Recommended testing tools

Finally, it takes 888ms to complete the rendering of the first Activity from the App launcher click, which is lucky!

·  Time to full Display

The log line above is printed by the system and represents the time it took to render the Acitivity, including the time it took to start the first Activity. This Log will only be Displayed on Android4.4 (API19) or above. You can see not only your own APP but also the startup time of other apps.

Attached is a piece of mi 4 on the industry’s major App cold startup time ~ for reference only ~

Hugo,

Execution time printing magic, integrated into the project, just add a note where you want to test:

This can be at the class level or function level. If the annotation is Appication class level, it will also print out the execution times of the major lifecycle callback functions. (https://github.com/JakeWharton/hugo)

The effect is as follows:

·  Stetho

This is a debugger, and if you haven’t developed Android before, you’ll feel like you’ve never seen it before!


If you think our content is good, please forward it to moments and share it with your friends