Android App ~ 第三方库使用 ContentProvider 初始化

情景模拟

最近小明开源了一个 Android 三方库,接入流程很简单,开发者们只需要在应用的 Application 的 onCreate() 方法中去初始化它,然后就可以调用相应的库 API 了

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        XiaomingLibrary.init(this);
    }
}

这是一个很常见的三方库接入后的初始化流程,但是有没有将库的初始化流程这一步再缩减,让开发者的接入流程更简单呢?如果有的话,像 leakcanary 这种仅需要在 Application 中初始化,又并不需要调用任何 API 的库将会带给开发者一种无任何侵入式的感受。答案当然是有的,作为一个库开发者,你可以在你的库中创建一个 ContentProvider,然后在 ContentProvider 的 onCreate() 方法中借助 getContext() 返回的 Context 来完成你的库初始化,当然,这个 Context 的实际类型就是应用的 Application。

调用时机

那么 ContentProvider 的 onCreate() 方法是什么时候被调用的呢?它是介于 Application 的 attachBaseContext(Context) 和 onCreate() 之间所调用的,Application 的 attachBaseContext(Context) 方法被调用这就意味着 Application 的 Context 被初始化了。简单带过一下源码,更加具体的源码解析可以参考 gityuan 的文章——

在应用的启动过程中,会走到 ActivityThread 的 handleBindApplication() 方法中,在该方法中可以看到 app = makeApplication()、installContentProviders(app)、mInstrumentation.callApplicationOnCreate(app) 三个方法被相继调用

实际上到这里源码实际上就可以解析完了,从方法名其实就可以看出 makeApplication() 是创建了 Application 并将 Application 实例赋给了 app 这个局部变量,接着 installContentProviders(app) 中会使得 ContentProvider 借助 app 这个局部变量初始化,最后 callApplicationOnCreate(app) 肯定就是调用了这个 app 的 onCreate() 方法。具体流程如下:

makeApplication() 调用链:
>
LoadedApk#makeApplication() -> Instrumentation#newApplication() -> Instrumentation.newApplication() -> Application#attach() -> Application#attachBaseContext()

installContentProviders() 调用链:
>
ActivityThread#installContentProviders() -> ActivityThread#installProvider() -> ContentProvider#attachInfo() -> ContentProvider.this.onCreate()

callApplicationOnCreate 调用链:
>
Instrumentation#callApplicationOnCreate() -> Application#onCreate()
<provider
    android:name="com.test.MyProvider"
    android:authorities="com.test.provider.authority"
    android:multiprocess="true"
    android:process=":core" />

我们知道默认不指定android:process的话,provider组件所在的进程名就是包名
multiprocess默认为false,则provider会随着应用启动的时候加载

如果对provider指定android:process和android:multiprocess,那么会产生如下几种情况:

  • android:process=“:core”,android:multiprocess=“true”:
    provider不会随应用的启动而加载,当调用到provider的时候才会加载,加载时provider是在调用者的进程中初始化的。这时候可能定义provider的core进程还没有启动。

  • android:process=“:core”(android:multiprocess默认情况下为"false"):
    provider不会随应用的启动而加载,当调用到provider的时候才会加载,加载时provider是在“fore”进程中初始化的。

  • android:multiprocess=“true”:
    provider会随着应用启动的时候加载,加载时provider是在应用默认主进程中初始化的。对于android:multiprocess=true,意味着provider可以多实例,那么由调用者在自己的进程空间实例化一个ContentProvider对象,此时定义ContentProvider的App可能并没有启动。

  • android:multiprocess=“false”:
    provider会随着应用启动的时候加载,加载时provider是在应用默认主进程中初始化的。对于android:multiprocess=false(默认值),由系统把定义该ContentProvider的App启动起来(一个独立的Process)并实例化ContentProvider,这种ContentProvider只有一个实例,运行在自己App的Process中。所有调用者共享该ContentProvider实例,调用者与ContentProvider实例位于两个不同的Process。

总之,android:multiprocess 应该理解为:是否允许在调用者的进程里实例化provider,而跟定义它的进程没有关系。

优缺点

优点: 很显而易见——免去了使用库的开发者们初始化库的流程,降低了接入成本,这种优势在像 leakcanary、BlockCanary 或者其他一些仅需要初始化而不需要开发者调用任何 API 的库上体现的更加明显,开发者只需要添加依赖就可以使用该库了,完全是0侵入式的接入流程。

缺点:缺点在于它并不一定适用于全部场景,因为 ContentProvider 的 onCreate() 执行在了 Application 的 onCreate() 方法之前,倘若你的库需要有其它业务的依赖(例如你的库需要在其它三方库依赖初始化完成之后才能够初始化)的话,这种方式就并不是很适配你的库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值