【译】你的Android库是否还在Application中初始化?

【译】你的Android库是否还在Application中初始化?

Android小彩虹2021-07-11 19:49:2090A+A-

原文: Your android libraries should not ask for an application context
作者:florent champigny@Idean
Markdown:原文 | 译文

通常来说,当我们引入一个第三方库,第一件要做的事情是在Application中的onCreate传入context初始化这个库 。但是为什么像一些库如Firebase,初始化的时候并不需要在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初始化。)

Useless

无需“初始化”的库

如果你的项目加入了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

Happy Dance

项目地址

github.com/florent37/A…

补充说明

没想到大家讨论这么厉害,感谢大家,学到很多。这里我找到了Firebase关于这种初始化方法的原文

How does Firebase initialize on Android?

看最后一段,作者对这种“滥用”ContentProvider表达了自己对观点

ContentProvider的此特定应用程序看起来确实很奇怪,因为它实际上并未提供任何内容。 并且您必须通过返回null提供所有其他ContentProvider必需方法的实现。 但是,事实证明,这是自动初始化而无需额外代码的最可靠方法。 我认为,使用Firebase为开发人员带来的便利远远超过了对ContentProvider使用这种奇怪之处的弥补。 Firebase就是关于易于使用的东西,没有什么比没有代码更容易了!

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1

联系我们