官網(wǎng)項(xiàng)目Jetpack?Startup庫(kù)學(xué)習(xí)
簡(jiǎn)單認(rèn)識(shí)一下Startup
nowinandroid項(xiàng)目作為目前google官方來(lái)演示MAD(現(xiàn)代Android開(kāi)發(fā)技術(shù))的示例項(xiàng)目,里面大量依賴運(yùn)用了jetpack包下的各種庫(kù)。通過(guò)分析學(xué)習(xí)這些庫(kù)在項(xiàng)中的實(shí)際使用可以幫助我們比直接閱讀庫(kù)的文檔來(lái)更好的理解和學(xué)習(xí)。希望通過(guò)學(xué)習(xí)后可以幫助到我們能熟練地在我們自己的項(xiàng)目中正確高效的使用到j(luò)etpack里面的各種強(qiáng)大庫(kù)。不廢話了,下面進(jìn)入我們今天的正題——Startup

App Startup | Android Developers 官網(wǎng)的指南有興趣可以看看
我們今天不講原理,你只需知道這個(gè)庫(kù)比之前用多個(gè)content provider去實(shí)現(xiàn)初始化更高效,更精確,更顯性,也就是說(shuō)能合并content provider提升app的啟動(dòng)速度,能準(zhǔn)確的控制初始化順序,能清晰的從代碼知道依賴關(guān)系。僅僅這些可能jym會(huì)說(shuō),我們項(xiàng)目不在乎那點(diǎn)啟動(dòng)速度的提升,也沒(méi)有很多三方庫(kù)需要走初始化等,根本用不到這個(gè)庫(kù)。
是的,我之前也是這么理解的,但是通過(guò)nowinandroid項(xiàng)目發(fā)現(xiàn),有些jetpack內(nèi)的其他庫(kù)的初始化現(xiàn)在也交給Startup來(lái)完成了,這一點(diǎn)就很重要了。意味著我們可以少寫(xiě)很多樣板代碼,少寫(xiě)也意味著少犯錯(cuò)。所以我覺(jué)的還是有必要單獨(dú)寫(xiě)一篇文章來(lái)說(shuō)說(shuō)Startup
編寫(xiě)初始化的代碼步驟很簡(jiǎn)單主要就分3步:
- 定義實(shí)現(xiàn)
Initializer接口的實(shí)現(xiàn)類 - 配置manifest
- 自動(dòng)或手動(dòng)調(diào)用初始化操作
OK了!就這簡(jiǎn)單3步,下面我們結(jié)合項(xiàng)目例子來(lái)看
項(xiàng)目代碼
- 先看第一步
object Sync {
// This method is a workaround to manually initialize the sync process instead of relying on
// automatic initialization with Androidx Startup. It is called from the app module's
// Application.onCreate() and should be only done once.
fun initialize(context: Context) {
AppInitializer.getInstance(context)
.initializeComponent(SyncInitializer::class.java)
}
}
internal const val SyncWorkName = "SyncWorkName"
/**
* Registers work to sync the data layer periodically on app startup.
*/
class SyncInitializer : Initializer<Sync> {
override fun create(context: Context): Sync {
WorkManager.getInstance(context).apply {
// Run sync on app startup and ensure only one sync worker runs at any time
enqueueUniqueWork(
SyncWorkName,
ExistingWorkPolicy.KEEP,
SyncWorker.startUpSyncWork(),
)
}
return Sync
}
override fun dependencies(): List<Class<out Initializer<*>>> =
listOf(WorkManagerInitializer::class.java)
}
定一個(gè)SyncInitializer類實(shí)現(xiàn)了泛型為Sync的Initializer接口。需要重寫(xiě)接口定義的兩個(gè)方法:
-
create()方法, 它包含初始化組件所需的所有操作,并返回一個(gè)Sync的實(shí)例. -
dependencies()方法, 返回當(dāng)前初始化器需要依賴的其他初始化器集合,我們可以用這個(gè)方法來(lái)變相的實(shí)現(xiàn)各個(gè)初始化器的執(zhí)行順序。
所以在create方法里面的執(zhí)行WorkManager.getInstance(context)方法是安全的。我們這篇只關(guān)注Startup所以我們只用知道在這個(gè)地方WorkManager做了些事情就行,后面會(huì)另開(kāi)一篇單獨(dú)講WorkManager。為啥是安全的呢?因?yàn)樵?code>dependencies方法里面先執(zhí)行了WorkManagerInitializer::class.java初始化。我們?cè)賮?lái)看看這個(gè)類。
public final class WorkManagerInitializer implements Initializer<WorkManager> {
private static final String TAG = Logger.tagWithPrefix("WrkMgrInitializer");
@NonNull
@Override
public WorkManager create(@NonNull Context context) {
// Initialize WorkManager with the default configuration.
Logger.get().debug(TAG, "Initializing WorkManager with default configuration.");
//這個(gè)地方已經(jīng)完成了單例的構(gòu)建,后面再調(diào)用WorkManager.getInstance(context)獲取實(shí)例,否則報(bào)錯(cuò)
WorkManager.initialize(context, new Configuration.Builder().build());
return WorkManager.getInstance(context);
}
@NonNull
@Override
public List<Class<? extends androidx.startup.Initializer<?>>> dependencies() {
//這里WorkManager的初始化不需要其他初始化構(gòu)造器,所以返回的是個(gè)空集合
return Collections.emptyList();
}
}
以上我們就把第一步走完了,現(xiàn)在再來(lái)看第二步
- 再看第二步
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- TODO: b/2173216 Disable auto sync startup till it works well with instrumented tests -->
<meta-data
android:name="com.google.samples.apps.nowinandroid.sync.initializers.SyncInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
</application>
</manifest>
這里需要注意的是tools:node="remove",在provider層級(jí)用的話是全局取消自動(dòng)初始化,在meta-data層級(jí)用的話是單個(gè)組件取消自動(dòng)初始化。例子展示的是單個(gè)組件取消自動(dòng)初始化。另外注意的一點(diǎn)是被依賴的初始化組件是不需要再另外在manifest里面聲明的,這就是為什么WorkManagerInitializer沒(méi)有聲明。
- 最后一步
@HiltAndroidApp
class NiaApplication : Application(), ImageLoaderFactory {
override fun onCreate() {
super.onCreate()
// Initialize Sync; the system responsible for keeping data in the app up to date.
Sync.initialize(context = this)
}
/**
* Since we're displaying SVGs in the app, Coil needs an ImageLoader which supports this
* format. During Coil's initialization it will call `applicationContext.newImageLoader()` to
* obtain an ImageLoader.
*
* @see <a rel="external nofollow" >Coil</a>
*/
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this)
.components {
add(SvgDecoder.Factory())
}
.build()
}
}
上面的代碼是app的Application,我們今天的重點(diǎn)是Startup,所以我們先不管其他的。只用看onCreate下的Sync.initialize(context = this)方法。
object Sync {
// This method is a workaround to manually initialize the sync process instead of relying on
// automatic initialization with Androidx Startup. It is called from the app module's
// Application.onCreate() and should be only done once.
fun initialize(context: Context) {
AppInitializer.getInstance(context)
.initializeComponent(SyncInitializer::class.java)
}
}
AppInitializer.getInstance(context).initializeComponent(SyncInitializer::class.java)傳入SyncInitializer類,實(shí)現(xiàn)手動(dòng)初始化完成。
以上就是nowinandroid項(xiàng)目對(duì)Startup庫(kù)的使用,并且上面我們也知道了我們自定義的初始化器在初始化的時(shí)候通過(guò)WorkManager做了些事情。那么下篇我們還是通過(guò)這個(gè)例子來(lái)看看nowinandroid是怎么使用WorkManager這個(gè)庫(kù)的,更多關(guān)于官網(wǎng)Jetpack Startup庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
自定義Adapter并通過(guò)布局泵LayoutInflater抓取layout模板編輯每一個(gè)item實(shí)現(xiàn)思路
自定義Adapter并通過(guò)布局泵LayoutInflater抓取layout模板編輯每一個(gè)item,下面我們開(kāi)始學(xué)習(xí)這一篇的內(nèi)容,感興趣的朋友可以了解下哈2013-06-06
Android 超詳細(xì)SplashScreen入門(mén)教程
Android 12正式版即將發(fā)布,有一個(gè)非常顯著的視覺(jué)變化就是,Android 12強(qiáng)制給所有的App都增加了SplashScreen的功能。是的,即使你什么都不做,只要你的App安裝到了Android 12手機(jī)上,都會(huì)自動(dòng)擁有這個(gè)新功能2022-03-03
Android滑動(dòng)拼圖驗(yàn)證碼控件使用方法詳解
這篇文章主要為大家詳細(xì)介紹了Android滑動(dòng)拼圖驗(yàn)證碼控件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Android讀取本地圖庫(kù)與調(diào)用攝像頭拍攝
這篇文章主要為大家詳細(xì)介紹了Android讀取本地圖庫(kù)與調(diào)用攝像頭拍攝,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Android中 webView調(diào)用JS出錯(cuò)的解決辦法
這篇文章主要介紹了Android中 webView調(diào)用JS出錯(cuò)的解決辦法,需要的朋友可以參考下2015-01-01
Android使用onCreateOptionsMenu()創(chuàng)建菜單Menu的方法詳解
這篇文章主要介紹了Android使用onCreateOptionsMenu()創(chuàng)建菜單Menu的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android基于onCreateOptionsMenu創(chuàng)建菜單的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2016-11-11

