How to Set for App When Loading First Does Not Load Again in Android Programming
Users await apps to be responsive and fast to load. An app with a ho-hum get-go time doesn't meet this expectation, and can be disappointing to users. This sort of poor feel may crusade a user to rate your app poorly on the Play store, or even abandon your app altogether.
This document provides information to help you optimize your app's launch time. It begins by explaining the internals of the launch process. Next, it discusses how to profile startup functioning. Last, it describes some common showtime-time issues, and gives some hints on how to accost them.
Understand the different app startup states
App launch can take place in one of three states, each affecting how long it takes for your app to become visible to the user: common cold commencement, warm start, or hot kickoff. In a cold start, your app starts from scratch. In the other states, the organisation needs to bring the running app from the background to the foreground. Nosotros recommend that you ever optimize based on an supposition of a cold get-go. Doing so tin can improve the performance of warm and hot starts, besides.
To optimize your app for fast startup, information technology's useful to understand what's happening at the organization and app levels, and how they collaborate, in each of these states.
Common cold offset
A cold start refers to an app's starting from scratch: the system's process has non, until this start, created the app'due south process. Cold starts happen in cases such as your app's beingness launched for the kickoff time since the device booted, or since the organisation killed the app. This type of start presents the greatest claiming in terms of minimizing startup fourth dimension, because the system and app have more piece of work to do than in the other launch states.
At the beginning of a cold start, the organisation has three tasks. These tasks are:
- Loading and launching the app.
- Displaying a blank starting window for the app immediately subsequently launch.
- Create the app procedure.
Every bit soon as the system creates the app process, the app process is responsible for the next stages:
- Creating the app object.
- Launching the principal thread.
- Creating the principal activity.
- Inflating views.
- Laying out the screen.
- Performing the initial draw.
Once the app process has completed the first describe, the arrangement process swaps out the currently displayed background window, replacing it with the main activeness. At this indicate, the user can start using the app.
Figure 1 shows how the organisation and app processes paw off piece of work between each other.
Performance bug can arise during creation of the app and creation of the activity.
Awarding creation
When your application launches, the blank starting window remains on the screen until the organization finishes drawing the app for the start fourth dimension. At that bespeak, the system process swaps out the starting window for your app, allowing the user to start interacting with the app.
If you've overridden Application.onCreate()
in your own app, the organisation invokes the onCreate()
method on your app object. Later, the app spawns the primary thread, also known as the UI thread, and tasks information technology with creating your main activeness.
From this bespeak, arrangement- and app-level processes proceed in accordance with the app lifecycle stages.
Activity creation
Later on the app process creates your activity, the activity performs the following operations:
- Initializes values.
- Calls constructors.
- Calls the callback method, such as
Activity.onCreate()
, appropriate to the current lifecycle state of the activeness.
Typically, the onCreate()
method has the greatest impact on load fourth dimension, because information technology performs the piece of work with the highest overhead: loading and inflating views, and initializing the objects needed for the activeness to run.
Warm kickoff
A warm starting time encompasses some subset of the operations that accept place during a cold start; at the aforementioned fourth dimension, it represents more overhead than a hot commencement. There are many potential states that could be considered warm starts. For instance:
-
The user backs out of your app, just then re-launches it. The procedure may have continued to run, but the app must recreate the activity from scratch via a call to
onCreate()
. -
The system evicts your app from retentiveness, and then the user re-launches information technology. The process and the action need to be restarted, just the task can benefit somewhat from the saved example land bundle passed into
onCreate()
.
Hot start
A hot start of your application is much simpler and lower-overhead than a cold first. In a hot showtime, all the system does is bring your activity to the foreground. If all of your application's activities are nonetheless resident in memory, then the app tin can avoid having to echo object initialization, layout aggrandizement, and rendering.
However, if some memory has been purged in response to memory trimming events, such as onTrimMemory()
then those objects volition demand to exist recreated in response to the hot outset event.
A hot start displays the aforementioned on-screen behavior as a cold start scenario:
The system process displays a blank screen until the app has finished rendering the activity.
Using metrics to observe and diagnose problems
In order to properly diagnose start fourth dimension performance, you can track metrics that show how long it takes your application to starting time. Android provides several means of letting you know that your app has a problem, and to help y'all diagnose it. Android vitals can alert you that the problem is occurring, and diagnostic tools can help you diagnose the problem.
Benefits of utilizing startup metrics
Android uses the Time to initial display and Time to full display metrics to optimize cold and warm awarding startups. Android Runtime (Fine art) uses the data from these metrics to efficiently precompile code for optimization of future startups.
Faster startups lead to more sustained user interaction with your app, which reduces instances of early on exiting, restarting the case, or navigating away to a different app.
Android vitals
Android vitals can help improve your app's performance by alerting you, via the Play Console, when your app'south startup times are excessive. Android vitals considers your app'due south startup times excessive when the app's:
- Cold startup takes v seconds or longer.
- Warm startup takes 2 seconds or longer.
- Hot startup takes ane.five seconds or longer.
Android vitals uses the Time to initial display metric and doesn't study data for hot startups. For information on how Google Play collects Android vitals data, see the Play Console documentation.
Time to initial display
The fourth dimension to initial display (TTID) metric measures the time it takes for an application to produce its get-go frame, including process initialization (if a cold start), activity creation (if cold/warm), and displaying commencement frame.
How to retrieve TTID
In Android 4.iv (API level xix) and higher, logcat includes an output line containing a value called Displayed
. This value represents the corporeality of time elapsed betwixt launching the procedure and finishing drawing the corresponding action on the screen. The elapsed time encompasses the following sequence of events:
- Launch the procedure.
- Initialize the objects.
- Create and initialize the activity.
- Inflate the layout.
- Depict your application for the first time.
The reported log line looks similar to the post-obit example:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
If you're tracking logcat output from the command line, or in a terminal, finding the elapsed time is straightforward. To find elapsed time in Android Studio, you must disable filters in your logcat view. Disabling the filters is necessary because the system server, not the app itself, serves this log.
Once yous've made the appropriate settings, you tin easily search for the correct term to see the fourth dimension. Effigy ii shows how to disable filters, and, in the 2nd line of output from the bottom, an example of logcat output of the Displayed
time.
The Displayed
metric in the logcat output does not necessarily capture the corporeality of time until all resources are loaded and displayed: information technology leaves out resources that are not referenced in the layout file or that the app creates as function of object initialization. Information technology excludes these resources because loading them is an inline process, and does not block the app'south initial display.
Sometimes the Displayed
line in the logcat output contains an additional field for total time. For example:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
In this case, the get-go time measurement is only for the activity that was first drawn. The total
time measurement begins at the app process offset, and could include another activity that was started get-go but did not display annihilation to the screen. The total
time measurement is only shown when there is a difference between the single activity and total startup times.
You can as well measure the time to initial brandish by running your app with the ADB Shell Activity Manager command. Hither's an instance:
adb [-d|-east|-due south <serialNumber>] shell am start -Southward -West com.example.app/.MainActivity -c android.intent.category.LAUNCHER -a android.intent.activeness.Master
The Displayed
metric appears in the logcat output every bit before. Your terminal window should also brandish the following:
Starting: Intent Activity: com.example.app/.MainActivity ThisTime: 2044 TotalTime: 2044 WaitTime: 2054 Complete
The -c
and -a
arguments are optional and let you lot specify <category>
and <activity>
Time to full display
The Fourth dimension to full brandish (TTFD) metric measures the time taken by the application to produce its first frame with full content, including content loaded asynchronously after the first frame. Generally, this is chief list content loaded from the network, as reported by the app.
How to retrive TTFD
You can use the reportFullyDrawn()
method to measure out the elapsed time between application launch and complete brandish of all resources and view hierarchies. This can exist valuable in cases where an app performs lazy loading. In lazy loading, an app does not block the initial cartoon of the window, but instead asynchronously loads resources and updates the view bureaucracy.
If, due to lazy loading, an app's initial display does not include all resources, y'all might consider the completed loading and display of all resources and views equally a separate metric: For instance, your UI might exist fully loaded, with some text drawn, but not yet display images that the app must fetch from the network.
To address this business organization, you can manually phone call reportFullyDrawn()
to let the system know that your activity is finished with its lazy loading. When you use this method, the value that logcat displays is the fourth dimension elapsed from the creation of the application object to the moment reportFullyDrawn()
is called. Here's an example of the logcat output:
system_process I/ActivityManager: Fully fatigued {bundle}/.MainActivity: +1s54ms
The logcat output sometimes includes a total
time, as discussed in Fourth dimension to initial display.
If you larn that your display times are slower than you'd similar, you can go along to endeavor to identify the bottlenecks in the startup procedure.
Identifying bottlenecks
A adept fashion to await for bottlenecks is to utilize the Android Studio CPU Profiler. For information, run into Inspect CPU action with CPU Profiler.
You can also gain insight into potential bottlenecks through inline tracing inside of your apps' and activities' onCreate()
methods. To acquire most inline tracing, encounter the documentation for the Trace
functions, and the overview of organisation tracing.
Be aware of common bug
This department discusses several issues that often affect apps' startup performance. These issues chiefly concern initializing app and action objects, too as the loading of screens.
Heavy app initialization
Launch operation can endure when your code overrides the Application
object, and executes heavy work or circuitous logic when initializing that object. Your app may waste product fourth dimension during startup if your Application subclasses perform initializations that don't need to be done yet. Some initializations may be completely unnecessary: for example, initializing state information for the primary action, when the app has actually started up in response to an intent. With an intent, the app uses simply a subset of the previously initialized state information.
Other challenges during app initialization include garbage-drove events that are impactful or numerous, or disk I/O happening concurrently with initialization, further blocking the initialization process. Garbage collection is especially a consideration with the Dalvik runtime; the Art runtime performs garbage collection meantime, minimizing that functioning's impact.
Diagnosing the problem
You tin use method tracing or inline tracing to try to diagnose the problem.
Method tracing
Running the CPU Profiler reveals that the callApplicationOnCreate()
method eventually calls your com.case.customApplication.onCreate
method. If the tool shows that these methods are taking a long time to finish executing, you lot should explore further to run across what piece of work is occurring in that location.
Inline tracing
Use inline tracing to investigate likely culprits including:
- Your app'due south initial
onCreate()
function. - Any global singleton objects your app initializes.
- Whatsoever disk I/O, deserialization, or tight loops that might be occurring during the bottleneck.
Solutions to the problem
Whether the problem lies with unnecessary initializations or with disk I/O, the solution is lazy initialization. In other words, you should just initialize objects that are immediately needed. Instead of creating global static objects, move to a singleton pattern where the app initializes objects just the first time it needs them.
Too, consider using a dependency injection framework like Hilt that creates objects and dependencies when they are injected for the first time.
If your app uses content providers to initialize app components at startup, consider using the App Startup library instead.
Heavy activity initialization
Action creation oftentimes entails a lot of high-overhead work. Frequently, there are opportunities to optimize this work to achieve performance improvements. Such common issues include:
- Inflating large or complex layouts.
- Blocking screen drawing on deejay, or network I/O.
- Loading and decoding bitmaps.
- Rasterizing
VectorDrawable
objects. - Initialization of other subsystems of the activity.
Diagnosing the problem
In this case, as well, both method tracing and inline tracing can bear witness useful.
Method tracing
When using the CPU Profiler, pay attention to your app'due south Awarding
subclass constructors and com.case.customApplication.onCreate()
methods.
If the tool shows that these methods are taking a long time to cease executing, yous should explore farther to see what piece of work is occurring there.
Inline tracing
Employ inline tracing to investigate likely culprits including:
- Your app'due south initial
onCreate()
function. - Any global singleton objects information technology initializes.
- Whatsoever disk I/O, deserialization, or tight loops that might exist occurring during the bottleneck.
Solutions to the problem
There are many potential bottlenecks, but two mutual problems and remedies are equally follows:
-
The larger your view hierarchy, the more than time the app takes to inflate it. Two steps you lot tin can take to address this issue are:
-
Flattening your view hierarchy by reducing redundant or nested layouts.
-
Not inflating parts of the. U. that do non demand to exist visible during launch. Instead, utilise a
ViewStub
object equally a placeholder for sub-hierarchies that the app can inflate at a more appropriate fourth dimension.
-
-
Having all of your resources initialization. on th. main thread can also slow downstartup.You can address this issue every bit follows:
- Move all resource initialization so that the app can perform it lazily on a different thread.
- Allow the appto. load and display your views, and thenlater update visual properties that are dependent on bitmaps and other resources.
Custom splash screens
You may run across extra time added during startup if you have previously used one of the following methods to implement a custom splash screen in Android 11 (API level xxx) or lower:
-
Using the
windowDisablePreview
theme aspect to plow off the initial blank screen drawn by the system during launch. -
Using a dedicated Activity
Starting with Android 12, migrating to the SplashScreen
API is required. This API enables a faster startup time, and also allows you lot to tweak your splash screen in the following means:
- Set a theme to change the splash screen's appearance
- Control how long the splash screen is displayed
- Determine how much more time the splash screen animation needs, and gracefully handle the animation for dismissing the splash screen
Furthermore, the compat library backports the SplashScreen API to enable astern-compatibility and to create a consequent look and feel for splash screen display across all Android versions.
See the Splash screen migration guide for details.
Source: https://developer.android.com/topic/performance/vitals/launch-time
0 Response to "How to Set for App When Loading First Does Not Load Again in Android Programming"
Post a Comment