来自大牛的启发

使用ContentProvider初始化你的Library

2018-01-08  本文已影响647人  蒸汽飞船

参考:
A

B
我们做项目的时候会用到很多库,不论是三方库还是或者是自己写的,不可避免的会要去初始化它们,一般都是在Application的oncreate里,那么我们现在会在Application里这么写:

@Override
public void onCreate() {
    super.onCreate();
    MyLib.init(this);
}

通过init方法传递一个Application进去并持有它。

这样做没什么错,但是在我看来是不太好的。

如果你使用过Lifecycle或者Firebase,你会发现你根本不用写哪怕一行的初始化代码就可以使用它,那么它们是怎么做的呢?

以Lifecycle为例:
我们去看Lifecycle的Manifest,其中会注册一个ContentProvider:

<provider
    android:name="android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
    android:authorities="xx.xx.xxxx.lifecycle-trojan"
    android:exported="false"
    android:multiprocess="true" />

而这个Provider的实现非常的简单:

public class LifecycleRuntimeTrojanProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        LifecycleDispatcher.init(getContext());
        ProcessLifecycleOwner.init(getContext());
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, String[] strings, String s, String[] strings1,
            String s1) {
        return null;
    }
    ...
   //return null or 0;
}

原理:我们都知道ContentProvider的onCreate的调用时机介于Application的attachBaseContext和onCreate之间,Provider的onCreate优先于Application的onCreate执行,并且此时的Application已经创建成功,而Provider里的context正是Application的对象,Lifecycle这么做,把init的逻辑放到库内部,让调用方完全不需要在Application里去进行初始化了,十分方便。

注意点:
使用ContentProvider初始化的方式,我们需要注意一下几点:
首先,在Manifest里设置ContentProvider的时候要设置一个authorities,这个authorities相当于ContentProvider的标识,是不能重复的,为了保证不重复,我们再设置这个值的时候最好不要硬编码,而是使用以下的这种方式:使用appid+xxx

<provider
    android:authorities="${applicationId}.xxprovider"
    android:name=".MyLibRuntimeProvider"
    android:exported="false"/>

由ActivityThread的handleBindApplication方法可以看到,是先调用installContentProviders方法,然后调用mInstrumentation.callApplicationOnCreate方法的。

上一篇下一篇

猜你喜欢

热点阅读