Future Android updates will gradually adopt this model: there will be fewer and fewer APIs related to specific systems , and more programming APIs will be provided to us in the form of Jetpack Library. In this way, we do not need to write a lot of adaptation logic specifically for different system versions, but can use the interface provided by Jetpack uniformly. Android is also using this method to solve the long-standing fragmentation problem.
Jetpack family has joined two new heavyweight members, Hilt and App Startup
In this post I will only focus on App Startup
App Startup is a library that can be used to speed up app startup.
what problem App Startup is used to solve
Before learning the usage of App Startup, the first thing we need to figure out is what problem App Startup is used to solve.
If you introduce a lot of third-party libraries into your project, the code in Application may be becomes like this:
class MyApplication : Application() { override fun onCreate() { super.onCreate() LitePal.initialize(this) AAA.initialize(this) BBB.initialize(this) CCC.initialize(this) DDD.initialize(this) EEE.initialize(this) } ... }
This code will look a little messy, right? As you reference more and more third-party libraries
Therefore, some smarter library designers have come up with a very clever way to avoid calling the initialization interface explicitly, but to call the initialization interface automatically. This method is with the help of ContentProvider
.
We all know that ContentProvider
is one of the four components of Android, and its main role is to share data across applications. For example, why we can read the contacts in the phone book, photos in the album and other data, with the help of ContentProvider.
However, these clever library designers didn’t intend to use ContentProvider to share data across applications, only to use it for initialization. Let’s look at the following code:
class MyProvider : ContentProvider() { override fun onCreate(): Boolean { context?.let { LitePal.initialize(it) } return true } ... }
Here I define a MyProvider
and let it inherit from ContentProvider
, and then we call the initialization
interface in the onCreate()
method. Note that the Context
can also be obtained in the ContentProvider
.
Of course, after inheriting ContentProvider
, we have to rewrite many methods, but other methods are completely unavailable in our scenario, so you can directly throw an exception in those methods, or implement empty implementations.
In addition, don’t forget that the four components need to be registered in the AndroidManifest.xml file before they can be used, so remember to add the following:
<application ...>
<provider
android:name=".MyProvider"
android:authorities="${applicationId}.myProvider"
android:exported="false" />
</application>
Code language: HTML, XML (xml)
So, when will this custom MyProvider be executed? Let’s take a look at this flowchart:

As you can see, the execution sequence of an application looks like this. First call the attachBaseContext()
method of the Application, then call the onCreate()
method of the ContentProvider
, and then call the onCreate()
method of the Application.
So, what happens if you implements the above MyProvider in your own library?
You will find that the interface of initialize()
can be omitted, because this interface will be called automatically in MyProvider
, so that your lib has actually been initialized when entering the onCreate()
method of Application.
Do you think this design method is very clever? It can further simplify the usage of the library. It does not require you to actively call the initialization interface, but quietly and automatically completes this work behind the scenes.
So what libraries use this design? There are really many of them, such as Facebook’s library, Firebase’s library, and the well-known WorkManager, Lifecycles and so on. None of these libraries provide an initialization interface
It looks like such an ingenious technical solution, so does it have any disadvantages?
Yes, the disadvantage is that ContentProvider
will add a lot of extra time.
After all, ContentProvider
is one of the four major components of Android, which is relatively heavyweight. That is to say, my initialization operation may have been a very lightweight operation, but after relying on ContentProvider
, it becomes a heavyweight operation.
Regarding the time-consuming of ContentProvider, Google officially gave a test result:

This was tested on a Pixel 2 phone running Android 10. It can be seen that an empty ContentProvider
will take about 2ms of time, and as the ContentProvider
increases, the time will also increase. If your application uses 50 ContentProviders, it will take close to 20ms.
Note that this is only the time spent on empty ContentProvider
, and does not count the time spent executing logic in ContentProvider.
This test result tells us that although the design method of using ContentProvider for initialization just introduced is very clever, if each third-party library creates a ContentProvider by itself, then the startup speed of our App will be greatly affected in the end. .
Yes, that why App Startup was introduced
I spent a long time above to introduce what problem App Startup is used to solve, because this part is the core of the App Startup library. Only by understanding what problem it is used to solve you can then quickly master it. usage. Otherwise, as I said at the beginning, I will learn how to learn how to learn ContentProvider, and I will be confused.
So how does App Startup solve this problem?
It can combine all the ContentProviders used for initialization into one, which makes the App launch faster.
Specifically, App Startup
also creates a ContentProvider
and provides a set of standards for initialization. Then for other third-party libraries, you don’t need to create ContentProviders yourself, just implement them according to my set of standards. I can guarantee that your libraries are successfully initialized before the App starts.
Knowing what problem App Startup
is used to solve and its implementation principle, then we start to learn its usage, this part is very simple.
To use App Startup
first, we need to import this library:
dependencies {
implementation "androidx.startup:startup-runtime:1.0.0-alpha01"
}
Code language: JavaScript (javascript)
Next we need to define an Initializer for performing initialization and implement the Initializer interface of the App Startup library as follows:
class LitePalInitializer : Initializer<Unit> { override fun create(context: Context) { LitePal.initialize(context) } override fun dependencies(): List<Class<out Initializer<*>>> { return listOf(OtherInitializer::class.java) } }
Implementing the Initializer interface requires reproducing two methods. In the create()
method, we can perform the previous initialization operations, and the create()
method will pass in the Context
parameters we need.
The dependencies()
method indicates whether the current LitePalInitializer still depends on other Initializers, and if so, configure it here. App Startup will ensure that the dependent Initializers are initialized first
Of course, in most cases, our initialization operations will not depend on other Initializers, so it is usually enough to return an emptyList()
directly, as shown below:
class LitePalInitializer : Initializer<Unit> { override fun create(context: Context) { LitePal.initialize(context) } override fun dependencies(): List<Class<out Initializer<*>>> { return emptyList() } }
After defining the Initializer, the last step is to configure it into AndroidManifest.xml. However, note that the configuration here has stricter format requirements, as shown below:
<application ...>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.example.LitePalInitializer"
android:value="androidx.startup" />
</provider>
</application>
Code language: HTML, XML (xml)
There are not many places that we can modify the above configuration. Only the android:name
part in the meta-data needs to be specified as the full path class name of our custom Initializer. Other parts cannot be modified, otherwise the App Startup library will not work properly.
Yes, the usage of the App Startup library is so simple, basically I summarize it into a three-step operation.
- Libraries that import App Startup.
- Customize an Initializer for initialization.
- Configure the custom Initializer into AndroidManifest.xml.
In this way, when the App starts, theContentProvider
built in the App Startup library will be automatically executed, and all registered Initializers will be searched in its ContentProvider, and then theircreate()
methods will be called one by one to perform initialization operations.
All libraries can be initialized normally with only one ContentProvider
Now let’s introduce a less commonly used knowledge point: lazy initialization.
lazy initialization
Now we know that all Initializers will automatically perform initialization operations when the App starts. But what if I don’t want it to be automatically initialized at startup, but manually at a specific time later on?
First, you have to find out what is the full path class name of the Initializer used by your lib to initialize , such as com.example.LitePalInitializer
in the above example (note that I only give an example here to explain this knowledge point)
Then, add the following configuration to the AndroidManifest.xml of your project:
<application ...>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.example.LitePalInitializer"
tools:node="remove" />
</provider>
</application>
Code language: HTML, XML (xml)
The difference is that a tool:node="remove"
tag is added to the meta-data of LitePalInitializer
.
This flag is used to tell the manifest merger tool to delete all meta-data nodes whose android:name
is com.example.LitePalInitializer
when it is finally packaged into an APK.
In this way, the Initializer configured by the library in its own AndroidManifest.xml will also be deleted. Since it is deleted, App Startup will definitely not be able to initialize it when it starts.
The code to manually initialize afterwards is also extremely simple, as shown below:
AppInitializer.getInstance(this)
.initializeComponent(LitePalInitializer::class.java)
Code language: CSS (css)
Just pass the LitePalInitializer into the initializeComponent() method, and the App Startup library will call its create()
method to perform the initialization operation according to the same standard.
So far, the functions of App Startup are basically explained.
In the end, if let me summarize, the overall usage of this library is very simple, but it may not be suitable for everyone. If you are a library developer and use the ContentProvider
method for initialization, then you should connect to App Startup, which can reduce the startup time of apps that access your library. And if you are an App developer, I think the probability of using ContentProvider for initialization is very low, so maybe App Startup is not very useful to you.
Of course, considering the code structure of business logic separation, App developers can also consider moving some initialization code originally placed in the Application to an Initializer for separate execution, which may make your code structure more reasonable and consistent
One Reply to “A new member of Jetpack: App Startup”