網站首頁 編程語言 正文
定義
- 一個可以用于加速App啟動速度的庫;
- 提供在 App 啟動時初始化組件簡單、高效的方法,可以使用 App Startup 顯示的設置初始化順序;
- 提供了一個 ContentProvider 來運行所有依賴項的初始化,避免每個第三方庫單獨使用 ContentProvider 進行初始化,從而提高了應用的程序的啟動速度;
解決了什么問題
- 如果你在項目當中引入了非常多的第三方庫,那么Application中的代碼就可能會變成這個樣子(這還只是我們實際項目的部分代碼):
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
CommonModule.init(this);
XCrash.init(this, new XCrash.InitParameters());
initQbSdk(this);
initRetrofit();
initDialogSetting();
initBugly();
initWeChat();
initUmeng();
initDoKit();
initNIM();
}
...
}
- 有些更加聰明的庫設計者,想到可以借助ContentProvider自動調用初始化接口,從而避免顯示的初始化:
//1. 繼承 ContentProvider,在onCreate中初始化
class MyProvider : ContentProvider() {
override fun onCreate(): Boolean {
context?.let {
//ContentProvider中也可以取得Context
LjyToastUtil.getInstance().init(it)
}
return true
}
//其他方法用不到,直接return null 或 return -1 即可
...
}
//2. ContentProvider是四大組件之一,需要在AndroidManifest.xml文件中進行注冊
<application ...>
...
<provider
android:name=".MyProvider"
//authorities的值沒有固定要求,但要保證該值在整個手機上是唯一的,所以通常會使用${applicationId}作為前綴,以防止和其他應用程序沖突
android:authorities="${applicationId}.myProvider"
android:exported="false" />
</application>
//3. 自定義的MyProvider在什么時候執行呢? 調用流程如下:
Application.attachBaseContext() -> ContentProvider.onCreate() -> Application.onCreate()
//這是在冷啟動階段自動運行初始化的,來看一下 Android 10 系統源碼
private void handleBindApplication(AppBindData data) {
...
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
// 創建ContentProvider
installContentProviders(app, data.providers);
}
}
...
try {
// 調用調用 Application 的 OnCreate 方法
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
...
}
- 此方案的缺點:ContentProvider會增加許多額外的耗時, ContentProvider是Android四大組件之一,這個組件相對來說是比較重量級的, 也就是說,本來我的初始化操作可能是一個非常輕量級的操作,依賴于ContentProvider之后就變成了一個重量級的操作了;
如何解決問題
- 鑒于前兩者的缺點,Google推出了App Startup
- App Startup是如何解決問題的呢?它可以將所有用于初始化的ContentProvider合并成一個,從而使App的啟動速度變得更快。
使用方法
1. 引入AppStartup依賴
implementation "androidx.startup:startup-runtime:1.1.0-alpha01"
2. 實現App Startup庫的Initializer接口
定義一個用于執行初始化的類,并實現App Startup庫的Initializer接口
class LjyToastInitializer : Initializer<Unit> {
//在create方法中執行要初始化的代碼
override fun create(context: Context) {
LjyToastUtil.getInstance().init(context)
}
//dependencies方法用于配置當前LjyToastInitializer是否還依賴于其他Initializer
//有的話在此配置,沒有就return emptyList()即可
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}
3. 在庫的AndroidManifest.xml中配置MyInitializer
<provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="com.jinyang.jetpackdemo.LjyToastInitializer" android:value="androidx.startup" /> </provider>
- 當App啟動的時候會自動執行App Startup庫中內置的ContentProvider,并在它的ContentProvider中會搜尋所有注冊的Initializer,然后逐個調用它們的create()方法來進行初始化操作;
延遲初始化
- 如果不希望在啟動的時候自動初始化某個庫,而是想要在特定的時機手動初始化,這要怎么辦呢?
- 首先通過分析源碼,找到該庫初始化的Initializer的全路徑類名
- 在項目的AndroidManifest.xml當中加入如下配置:
<provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="com.jinyang.jetpackdemo.LjyToastInitializer" android:value="androidx.startup" tools:node="remove" /> </provider>
- 禁用單個庫就在meta-data中加入tools:node="remove"
- 禁用所有庫就是在provider標簽中加入tools:node="remove"
- 然后在需要的地方去手動的初始化
AppInitializer.getInstance(this)
.initializeComponent(LjyToastInitializer::class.java)
- 延遲初始化也是非常有用的,可以減少 App 的啟動時間,提高啟動速度。
原文鏈接:https://zhuanlan.zhihu.com/p/405255928
相關推薦
- 2022-03-29 C++中的拷貝構造詳解_C 語言
- 2022-10-20 Flutter?StatefulBuilder實現局部刷新實例詳解_Android
- 2022-09-22 在容器內獲取 Pod 信息
- 2023-03-16 python內置函數anext的具體使用_python
- 2022-05-12 基于nginx反向代理獲取用戶真實Ip地址詳解_nginx
- 2022-11-02 react組件中過渡動畫的問題解決_React
- 2023-01-19 詳解Go語言實現線性查找算法和二分查找算法_Golang
- 2023-05-09 Python實現刪除重復文件的示例代碼_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支