【译】你的Android库是否还在Application中初始化?,译库网页翻译,但是为什么像一些库如Fi
【译】你的Android库是否还在Application中初始化?,译库网页翻译,但是为什么像一些库如Fi
通常来说,当我们引入一个第三方库,第一件要做的事情是在Application
中的onCreate
传入context
初始化这个库 。但是为什么像一些库如Firebase2019-10-19
,初始化的时候并不需要在Application
中初始化呢?今天我们就来探索一下这个问题
Android库的初始化
举个栗子,我们需要在app中国呢使用ARouter,在使用前需要初始化传入context
,因此如果没有application
时我们要创建一个:
class MainApplication : Application() { override fun onCreate(){ super.onCreate() ARouter.init(mApplication); } }
然后要在清单文件 AndroidManifest.xml
中声明才会执行 :
<application android:name=".MainApplication" ...
更多库怎么办
现在想象我们使用了ARouter,友盟统计,Realm,ToastUtils等库时,我们的application可能会是如下形式:
class MainApplication : Application() { override fun onCreate(){ super.onCreate() ARouter.init(this) UMConfigure.init(this,...) Realm.init(this) ToastUtils.init(this) } }
在项目中, 仅仅为了初始化一些库,我就必须得新建
Application
并且在onCreate
中调用它。(译者:也许你认为这也没什么,但是如果你自己创建了多个库需要context时,你每次得预留一个init方法暴露给调用者,使用时又得在application初始化。)

无需“初始化”的库
如果你的项目加入了Firebase , 你会发现它并没有要求初始化, 你只要使用它 :
这个数据库访问没有需要context
的传入,通过离线访问存储本地。可以猜测它有一个机制获取上下文application context
,自动完成初始化。
ContentProvider & Manifest-Merger
developer.android.com/studio/buil…
你的Apk文件只包含一个清单文件
AndroidManifest.xml
,但是你的Android Studio项目可能会有多个源集(main source set),构建变体(build variants),导入的库(imported libraries)构成。因此在编译构建app时,gradle插件会将多个manifest
文件合并到一个清单文件中去。
我们可以看下合并后的清单文件(目录如下):
app/build/intermediates/merged_manifests/MY_APP/processMY_APPDebugManifest/merged/AndroidManifest.xml
我们可以发现一个关于Firebase
库的provider
被引入到清单文件中:
使用Android Studio点击打开FirebaseInitProvider
, 我们知道了这个provider
通过this.getContext()
来访问上下文。
内容提供者ContentsProviders
会直接在Application创建后
完成初始化,因此通过它来完成library的初始化不失为一个好办法。
自动初始化我们的库
如果我们自定义了ToastUtils
库需要初始化,我们自己提供一个Provider
:
class ToastInitProvider : ContentProvider() { override fun onCreate(): Boolean { ToastUtils.init(context) return true } ... }
然后这个库中的AndroidManifest.xml
中加入它
<provider android:name=".ToastInitProvider" android:authorities="xxx.xx.ToastInitProvider" />
然后当我们使用这个ToastUtils
库时,无需添加额外的代码在项目中初始化它,直接使用它即可:
ToastUtils.show("this is toast")
Stetho.getInstance().configure(…)
删除Application
如果一些库没有使用InitProviders
,我们可以创建它:
class ARouterInitProvider : ContentProvider() { override fun onCreate(): Boolean { ARouter.init(this) return true } ... } class RealmInitProvider : ContentProvider() { override fun onCreate(): Boolean { Realm.init(this) return true } ... }
然后加入到清单文件AndroidManifest
中 :
<provider android:name=".ARouterInitProvider" android:authorities="${applicationId}.ARouterInitProvider" /> <provider android:name=".RealmInitProvider" android:authorities="${applicationId}.RealmInitProvider" />
现在我们可以 移除
这个 MainApplication
项目地址
github.com/florent37/A…
补充说明
没想到大家讨论这么厉害,感谢大家,学到很多。这里我找到了Firebase
关于这种初始化方法的原文
How does Firebase initialize on Android?
看最后一段,作者对这种“滥用”ContentProvider
表达了自己对观点
用户评论