APP加载资源
我们APP中经常会用到图片,颜色等资源,但是你是否清楚这些资源是从什么时机,如何加载到我们的页面吗
加载思维导图
image.png流程总结:
1.activtyThread的handerbindApplication开始,里面创建仪表盘,并调用Application的onCreate方法,调用loadedApk的makeApplication方法
2.这个方法中创建contextImpl类ContextImpl.createAppContext,这个里面调用contextImpl 的.setResources方法加载资源。资源参数是packageInfo.getResource()
3.资源调用ResourcesManager.getInstance().getResources获取,里面调用createResources方法创建,findOrCreateResourcesImplForKeyLocked 里面再AssetManager assets = createAssetManager ,最后是通过setApkAssert调用native方法实现加载资源。
源码分析
1.入口和View创建在同一个类,ActivityThread中,handleBindApplication()开始,主要就三个核心点:1.创建Instrumentation对象,2,调用AppBindData.loadAPKInfo.makeApplication()创建Application,3再调用我们一般APP初始化的地方Application的onCreate方法
/* 1.创建Instrumentation对象*/
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
...
/* 2.创建application对象*/
app = data.info.makeApplication(data.restrictedBackupMode, null);
// Propagate autofill compat state
app.setAutofillOptions(data.autofillOptions);
// Propagate Content Capture options
app.setContentCaptureOptions(data.contentCaptureOptions);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
/* 3.通过Instrumentation对象调用Application的 onCreate方法*/
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
2.上面方法2调用了
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
3.里面调用了createAppContext方法
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
/**1,这里set资源*/
context.setResources(packageInfo.getResources());
context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context);
return context;
}
4.调用到getResouce方法
public Resources getResources() {
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
getClassLoader(), null);
}
return mResources;
}
5.又从LoadedApk方法,调到ResourcesManager.getInstance().getResources
public @Nullable Resources getResources(
@Nullable IBinder activityToken,
@Nullable String resDir,
@Nullable String[] splitResDirs,
@Nullable String[] overlayDirs,
@Nullable String[] libDirs,
int displayId,
@Nullable Configuration overrideConfig,
@NonNull CompatibilityInfo compatInfo,
@Nullable ClassLoader classLoader,
@Nullable List<ResourcesLoader> loaders) {
...
return createResources(activityToken, key, classLoader);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
}
直接看createResources方法,里面调用了
private @Nullable Resources createResources(@Nullable IBinder activityToken,
@NonNull ResourcesKey key, @NonNull ClassLoader classLoader) {
synchronized (this) {
if (DEBUG) {
Throwable here = new Throwable();
here.fillInStackTrace();
Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
}
ResourcesImpl resourcesImpl = findOrCreateResourcesImplForKeyLocked(key);
if (resourcesImpl == null) {
return null;
}
if (activityToken != null) {
return createResourcesForActivityLocked(activityToken, classLoader,
resourcesImpl, key.mCompatInfo);
} else {
return createResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
}
}
}
看这个方法 findOrCreateResourcesImplForKeyLocked(key里面终于调用到 createResourcesImpl(key) ,这里就到咯Assert类类
private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) {
final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
daj.setCompatibilityInfo(key.mCompatInfo);
final AssetManager assets = createAssetManager(key);
if (assets == null) {
return null;
}
final DisplayMetrics dm = getDisplayMetrics(key.mDisplayId, daj);
final Configuration config = generateConfig(key, dm);
final ResourcesImpl impl = new ResourcesImpl(assets, dm, config, daj);
if (DEBUG) {
Slog.d(TAG, "- creating impl=" + impl + " with key: " + key);
}
return impl;
}
再调用到加载资源到setApkAssets完成资源加载,调用native方法实现
网友评论