Android App startup speed optimization implementation walkthrough

Android App startup speed optimization implementation walkthrough

This article from the Jade just said writing platform provides writing sponsorship, belongs to Yu Gang said micro-channel public numbers of all
the author: Luo Zhanwei
Copyright: Jade just said, without permission, shall not be reproduced in any form

App startup method: cold start, hot start, warm start

Cold start

Cold start means that the APP runs for the first time after the phone is started, or restarts after the APP process is killed. It can be seen that the necessary condition for a cold start is that the APP process does not exist, which means that the system needs to create a process and the APP needs to be initialized. Among the three starting methods, cold start takes the longest time, and cold start optimization is also the most challenging. Therefore, this article focuses on optimizations related to cold start.

Warm start

The App process exists, and the Activity may be recycled due to insufficient memory at that time. At this time, starting the App does not need to re-create the process, but the onCrate of the Activity still needs to be re-executed. The scene is similar to opening Taobao for a walk, then switching to WeChat to chat, and returning to Taobao again after half an hour. At this time, the Taobao process exists, but the Activity may be recycled. At this time, you only need to reload the Activity.

Hot start

The App process exists, and the Activity object still exists in the memory and has not been recycled. You can repeatedly avoid object initialization, layout analysis and drawing. The scenario is similar to when you open WeChat and chat for a while. When you go out and check the calendar, when you open WeChat, it is a cold start.

What is the relationship between locking the App in the recent task and the startup method?

Some manufacturers provide the function of locking the APP for user experience, the purpose is to let the user make the decision. The locked APP will not be killed, and it will not be in a cold start mode when starting, but locking is not a panacea. The killer will also kill the locked APP when the memory is extremely tight, and it will also run in a cold start mode when it is started.

What is the relationship between AI and startup methods

AI can be very promising in process management. MIUI10 released the process AI wake-up function, which makes APP start faster than friends. The reason for this is simply to learn the user's usage habits, create the App process in advance, and not go out to cold start when the user opens the APP. For example, if you are a heavy user of WeChat, you find that after using MIUI10, you will no longer see the earth on the WeChat startup page. This is the credit of AI awakening.

Steps to go through from clicking the APP icon to the homepage display

Here we discuss the process of cold start. In principle, there are four ways to start a process, that is, through other processes calling the four major components of the APP to achieve.

Here we focus on the APP startup after the user clicks on the desktop, and the startup through startActivity. Call startActivity, this method is called layer by layer, and finally call startSpecificActivityLocked in ActivityStackSupervisor.java.When the process to which the activity belongs has not been started, you need to create the corresponding process.

void startSpecificActivityLocked(...) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    if (app != null && app.thread != null) {
         ...//
        return
    }
   //
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
}
 

The final process is the Zygote Fork process:


After the process is started, the system has another job: the blank start window of the application is displayed immediately after the process is started.

Once the system creates the application process, the application process will be responsible for the next stage. These stages are:
1. Create the application object
2. Start the main thread
3. Create the main Activity
4. Draw the view (View)
5. Layout the screen
6. Perform initial drawing

Once the App process completes the first drawing, the system process will replace the displayed Background Window with Main Activity, and the user can use the App at this time.

image.png

There are obviously two optimization points here:
Application OnCrate() optimization
When the APP starts, the blank startup window will remain on the screen until the system finishes drawing the application for the first time. At this point, the system process will exchange the start window of the application, allowing the user to start interacting with the application. If Application.onCreate() is overloaded in the application, the system will call the onCreate() method. After that, the application will spawn the main thread (also known as the UI thread) and perform tasks by creating a MainActivity.
The Activity onCreate() optimization
onCreate() method has the greatest impact on the load time, because it performs work with the highest overhead: loading and drawing the view, and initializing the objects required by the Activity to run.

Start speed optimization

How to quantify the startup time?

1. The most awesome thing I have seen so far is to use the robot and high-speed camera to test. After the mobile phone is turned on, use the robot to click on the application desktop icon, the high-speed camera records the startup process, and then analyze the video through the program, from the robot click on the icon to the Activity display. How much time did it take. This method is the most intuitive and accurate, but the cost is also high.

2. Via shell command

adb shell am start -W [packageName]/[packageName.MainActivity]
 

After successful execution, three measured times will be returned:
ThisTime: Generally the same as TotalTime, unless a transparent Activity is opened when the application starts to pre-process some things and then display the main Activity, which will be smaller than TotalTime.
TotalTime: The startup time of the application, including the creation process + Application initialization + Activity initialization to the interface display.
WaitTime: Generally larger than TotalTime, including the time-consuming impact of the system.

3. You can calculate the startup time by adding log to the code 4. Use systrace

Application OnCrate() optimization

1. The processing of third-party SDK initialization
Application is the main entry point of the program. Many third-party SDK sample programs require you to perform initialization operations during Application OnCreate. This is the main culprit for increasing the Application OnCreate time, so it is necessary to avoid synchronous initialization operations during Application onCreate. A better solution is to lazily load the three-party SDK, not initialize it during Application OnCreate(), and load it when it is actually used.
The following example compares ImageLoader's startup speed optimization after lazy loading.

Generally, when we use imageLoader, we will load it on the main thread during Application onCreate():

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ImageLoaderConfiguration.Builder config =
                new ImageLoaderConfiguration.Builder(this);
        ImageLoader.getInstance().init(config.build());
    }
}
 

At this time, use adb shell am start -W [packageName]/[packageName.MainActivity] to detect the start time of the application, and you need to kill the process every time you execute a command.

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.luozhanwei.myapplication/.MainActivity }
Status: ok
Activity: com.luozhanwei.myapplication/.MainActivity
ThisTime: 423
TotalTime: 423
WaitTime: 441
 

The total time is between 423ms. The following is an example of a tool class that encapsulates a lazy loading ImageLoader:

public class ImageUtil {

    private static boolean sInit;

    private synchronized static void ensureInit() {
        if (sInit) {
            return;
        }
        ImageLoaderConfiguration.Builder config =
                new ImageLoaderConfiguration.Builder(SecurityCoreApplication.getInstance());
      ....
       //Initialize ImageLoader with configuration.
        ImageLoader.getInstance().init(config.build());
        sInit = true;
    }

public static void display(String uri, ImageView imageView, boolean cacheOnDisk) {
        imageView.setImageResource(R.drawable.icon_app_default);
        ensureInit();
        ImageLoader loader = ImageLoader.getInstance();
        if (cacheOnDisk) {
            loader.displayImage(uri, imageView);
        } else {
            loader.displayImage(uri, imageView, OPTIONS_NO_CACHE_DISK);
        }
    }

 

Start-up time after using this scheme:

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.luozhanwei.myapplication/.MainActivity }
Status: ok
Activity: com.luozhanwei.myapplication/.MainActivity
ThisTime: 389
TotalTime: 389
WaitTime: 405
 

See that TotalTime is reduced by 34ms than before (the data given is the average of 10 tests).

Therefore, Application OnCreate avoids doing a lot of time-consuming operations in the main thread, such as IO-related logic, which will affect the startup speed of the application. If you must do it, you need to put it in a child thread.

Activity onCreate () optimization

Reduce the View level of LaunchActivity and reduce the time of View measurement and drawing. Avoid time-consuming operations on the main thread

User experience optimization

Eliminate the white/black screen at startup


Cold start white screen.gif

Why is there a brief black or white screen when starting up? When the user clicks on your app and the system calls Activity.onCreate() in this period of time, WindowManager will first load the windowBackground in the app theme style as the preview element of the app, and then actually load the activity's layout layout . Obviously, if your application or activity startup process is too slow, causing the system's BackgroundWindow to not be replaced in time, there will be a white or black screen at startup (depending on whether your theme is Dark or Light).


Solution
1.
Use transparent theme <item name="android:windowIsTranslucent">true</item>
Activity.onCreate() before the App does not display, so the user mistakenly thinks that the phone is slow, this kind of trick Don't use the plan.

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>

</resources>
 

The effect is as follows:


Shake the pot.gif

2. Theme replacement. We customize a style Lancher in style, and put a background image or advertisement image in it.

<style name="AppTheme.Launcher">
        <item name="android:windowBackground">@drawable/bg</item>
    </style>
 

Set this style to the started Activity

<activity
            android:name=".activity.SplashActivity"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme.Launcher"
            >
 

Then in the onCreate method of Activity, set the Activity back to the original theme

@Override
    protected void onCreate(Bundle savedInstanceState) {
       //onCreate 
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
    }
 

This prevents the embarrassment of the black and white screen by showing the user a picture or advertisement at startup.


Add start page.gif