很多第三方框架或SDK都会有个初始化操作,比如在Application的onCreate中调用XXX.init(),最近学习了LeakCanary的做法,就不再需要手动初始化了,那么自动初始化该怎么做呢?
首先定义一个InitProvider,它是继承于ContentProvider的一个子类。然后在AndroidManifest.xml中注册这个ContentProvider。
public class InitProvider extends ContentProvider {
@Override
public boolean onCreate() {
Context application = getContext().getApplicationContext();
if (application == null) {
application = CommonUtils.getApplicationByReflect();
}
//initSdk();
return true;
}
//xxxx
}
<application>
<provider
android:name=".InitProvider"
android:authorities="com.ry.tzui.InitProvider"
android:exported="false"
android:multiprocess="true" />
</application>
现象:ContentProvider的onCreate会先于Appliction的onCreate调用
原理:其实Appliction的onCreate,是Instrumentation调用了callApplicationOnCreate方法,然后这个方法是在ActivityThread的handleBindApplication方法中调用的。并且在callApplicationOnCreate方法前有个installContentProviders的方法,这个方法就是创建所有在AndroidManifest.xml注册过的ContentProvider。
ActivtyThread#handleBindApplication(AppBindData data)
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
}
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
try {
mInstrumentation.callApplicationOnCreate(app);
}
最后贴上方法
public class CommonUtils {
public static Application getApplicationByReflect() {
try {
@SuppressLint("PrivateApi")
Class<?> activityThread = Class.forName("android.app.ActivityThread");
Object thread = activityThread.getMethod("currentActivityThread").invoke(null);
Object app = activityThread.getMethod("getApplication").invoke(thread);
if (app == null) {
throw new NullPointerException("you should init first");
}
return (Application) app;
} catch (Exception e) {
e.printStackTrace();
}
throw new NullPointerException("you should init first");
}
}