在聊这个话题之前,先聊一下Lifecycle。
熟悉Lifecycle的人应该知道,Activity分发生命周期事件是通过LifecycleDispatcher
和ProcessLifecycleOwner
实现的,而这两个类的初始化都是在ProcessLifecycleOwnerInitializer
中进行初始化的。
public class ProcessLifecycleOwnerInitializer extends ContentProvider {
@Override
public boolean onCreate() {
LifecycleDispatcher.init(getContext());
ProcessLifecycleOwner.init(getContext());
return true;
}
}
ProcessLifecycleOwnerInitializer实际上是一个ContentProvider
,ContentProvider会在应用初始化的时候回调onCreate
方法,Lifecycle的设计者正是借鉴这一特性在ContentProvider做了初始化。
不熟悉Lifecycle的同学也不要慌,可以看看这篇博文,讲的很详细:Lifecycle源码分析 | Kyleduo's blog!
那么Lifecycle是如何在我们的app中注册这个ContentProvider的呢?毕竟我们可没在app的AndroidManifest文件中注册这个ContentProvider。
打开打包生成的apk文件,查看AndroidManifest.xml
,可以找到:
<provider
android:name="android.arch.lifecycle.ProcessLifecycleOwnerInitializer"
android:exported="false"
android:multiprocess="true"
android:authorities="dev.chenwei.livedatademo.lifecycle-trojan" />
想必是在extensions
库中注册的这个ContentProvider。
查看android.arch.lifecycle:extensions的aar,打开AndroidManifest文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.arch.lifecycle.extensions" >
<uses-sdk android:minSdkVersion="14" />
<application>
<provider
android:name="android.arch.lifecycle.ProcessLifecycleOwnerInitializer"
android:authorities="${applicationId}.lifecycle-trojan"
android:exported="false"
android:multiprocess="true" />
</application>
</manifest>
这里还使用了${applicationId}
占位符,避免authroities冲突。
既然Lifecycle的设计者通过ContentProvider完成初始化,那么其他三方库是不是可以借鉴这一思想,更进一步的简化三方库的注入呢?
我们同样可以定义一个ContentProvider,在onCreate方法中做初始化操作:
class LibraryInitializer: ContentProvider() {
override fun onCreate(): Boolean {
// 可以拿到ApplicationContext进行有些初始化操作
return true
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
return null
}
override fun query(
uri: Uri,
projection: Array<String>?,
selection: String?,
selectionArgs: Array<String>?,
sortOrder: String?
): Cursor? {
return null
}
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int {
return 0
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
return 0
}
override fun getType(uri: Uri): String? {
return null
}
}
然后在Module内部的AndroidManifest.xml中注册该ContentProvider即可。
PS:国外一大神在16年就发现了这一奇技淫巧 Auto-initialize your android library - André Tietz - Medium
在文章中还提出了applicationId没有配置的兜底方案,并且讨论了使用该方案的弊端。