On October 28, 2020, JetPack | App Startup 1.0.0 finally ushered in the official release.
The application startup library provides a simple and efficient way to initialize components when the application starts. Both library developers and application developers can use application startup to simplify the startup sequence and explicitly set the initialization order.
Instead of defining a separate content provider for each component that needs to be initialized, App Startup allows you to define component initializers that share a single content provider. This can significantly reduce application startup time.
Table of contents
Pre-knowledge
The content of this article will involve the following pre-requisite/related knowledge, and I have prepared it for you, please enjoy~
- ContentProvider component analysis: Android | ContentProvider working process
1. Why use App Startup?
In this section, let's discuss why App Startup is used, that is, what problems App Startup solves.
The non-invasive method of obtaining Context based on the ContentProvider startup mechanism : "Android | Use ContentProvider to obtain Context without intrusion" . Here I briefly recap:
- 1. In the second-party library or third-party library, it is often necessary to obtain the Context for initialization;
- 2. Because the ContentProvider will be initialized when the application starts, many libraries use the ContentProvider startup mechanism
Application#onCreate()
to initialize in it, such as LeakCanary 2.4 :
AppWatcherInstaller.java
internal sealed class AppWatcherInstaller : ContentProvider() {
internal class MainProcess : AppWatcherInstaller()
internal class LeakCanaryProcess : AppWatcherInstaller()
override fun onCreate(): Boolean {
val application = context!!.applicationContext as Application
AppWatcher.manualInstall(application)
return true
}
// 其他方法直接 return
}
- 3. The risk of this approach is that there are too many ContentProviders, and starting too many ContentProviders will increase the startup time of the application.
- 4. AppStartup's approach is to merge all ContentProviders used for initialization, reduce the creation of ContentProviders, and provide global management .
2. Steps to use
In this section, let's summarize the steps of using App Startup. The dependencies are as follows:
build.gradle
implementation "androidx.startup:startup-runtime:1.0.0"
2.1 Implement the Initializer interface for the component
Initializer
The interface is the component interface encapsulated by Startup, which is used to specify the initialization logic and initialization sequence (that is, the dependency relationship) of the component.
Initializer.java
public interface Initializer<T> {
1、初始化操作,返回的初始化结果将被缓存
@NonNull
T create(@NonNull Context context);
2、依赖关系,返回值是一个依赖组件的列表
@NonNull
List<Class<? extends Initializer<?>>> dependencies();
}
- 1.
create(...)
Initialization operation: the returned initialization result will be cached, andcontext
the parameter is Application; - 2.
dependencies()
Dependency: The return value is a list of dependent components. If there is no need to depend on other components, return an empty list. When App Startup initializes the current component, it will ensure that the dependent components have been initialized.
2.2 Automatic initialization
As mentioned earlier, App Startup merges all ContentProviders used for initialization. The merged ContentProvider is what InitializationProvider
we need to AndroidManifest
declare in, for example:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.example.ExampleLoggerInitializer"
android:value="androidx.startup" />
</provider>
The main points are as follows:
- 1. The component name must be
androidx.startup.InitializationProvider
; - 2. A statement is required
android:exported="false"
to restrict other applications from accessing this component; - 3. It is required to be
android:authorities
unique in the entire mobile phone, usually using ${applicationId} as a prefix; - 4. It needs to be declared
tools:node="merge"
to ensure thatmanifest merger tool
the conflicting nodes can be resolved correctly; - 5. Meta-data
name
is the fully qualified name of the component's Initializer implementation class,value
which isandroidx.startup
.
Tip: Why would you want to
androidx.startup
set it tovalue
, instead ofname
? Because the key-value pairname
is unique,value
but duplicates are allowed.
About AndroidManifest
how App Startup automatically performs initialization after declaring components in , I said in Section 3 .
2.3 Manual initialization
When a component needs to be lazy loaded (a time-consuming task), manual initialization can be performed. Initializers that require manual initialization do not need AndroidManifest
to be declared in , nor should they be relied upon by other components. Manual initialization can be done by calling:
AppInitializer.getInstance(context)
.initializeComponent(ExampleLoggerInitializer::class.java)
It should be noted that the initialization result will be cached in App Startup, and repeated calls initializeComponent()
will not lead to repeated initialization. About the source code analysis of the manual initialization part of App Startup, I said in Section 3 .
2.4 Cancel automatic initialization
If some libraries have been configured with automatic initialization using the method in section 2.2 , and we want to perform lazy loading, we need to use the manifest merger tool
merge rules to remove the corresponding Initializer of this library. details as follows:
<provider
android:name="andro