一般来说,一个Library都需要传入一个Context参数以完成初始化,该Context参数可以从Application对象的onCreate方法中获取。因此,大部分库都会提供一个init方法,让你在Application Object中完成调用,本文就介绍另一个方法。首先来看下你现在的代码,可能是这个样子:
public class YourApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SomeLibrary.init(this);
SomeOtherLibrary.init(this);
}
}
这种方法的坏处就是会逼着你一定要写一个Application对象,否则就用不了其他的依赖库,对于处女座来说有时候会觉得很不美好。让我们来换个思路进行这件事,这也是从Firebase的客户端得到的灵感,我们首先创建一个空的ContentProvider,然后再manifest文件中完成注册,不过别把它开放给其他应用。而在应用初始化的时候,它会调用onCreate方法注册全部的ContentProvider,这也就意味着虽然Activity还没有启动,但是可以访问ApplicationContext了,在这里我们也就能初始化那些依赖库了。
public final class YourLibraryInitProvider extends ContentProvider {
public YourLibraryInitProvider() {
}
@Override
public boolean onCreate() {
// get the context (Application context)
Context context = getContext();
// initialize whatever you need
}
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
<manifest package="some.library.packagename"
xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<provider
android:authorities="${applicationId}.yourlibraryinitprovider"
android:exported="false"
android:enabled="true"
android:name=".YourLibraryInitProvider" />
</application>
</manifest>
这边有个需要注意的点,就是如果是有固定的字符串,可能在有些设备上就无法运行,因此要保证authorities的属性的唯一性,这也就是传入applicationID的原因:
public final class YourLibraryInitProvider extends ContentProvider {
...
@Override
public void attachInfo(Context context, ProviderInfo providerInfo) {
if (providerInfo == null) {
throw new NullPointerException("YourLibraryInitProvider ProviderInfo cannot be null.");
}
// So if the authorities equal the library internal ones, the developer forgot to set his applicationId
if ("<your-library-applicationid>.yourlibraryinitprovider".equals(providerInfo.authority)) {
throw new IllegalStateException("Incorrect provider authority in manifest. Most likely due to a "
+ "missing applicationId variable in application\'s build.gradle.");
}
super.attachInfo(context, providerInfo);
}
...
}
不过这种方法的坏处就是因为所有的ContentProvider都是运行在主线程中,也就意味着所有的初始化都会在主线程完成。如果你希望要异步的初始化一些库,那么可以选择还是手动地在某个地方进行初始化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。