Android中的Resources解析

来源:互联网 发布:mysql 状态 编辑:程序博客网 时间:2024/06/08 17:08

下面我们从Application的创建说起

/frameworks/base/core/java/android/app/ActivityThread.java

private void handleBindApplication(AppBindData data) {    // 1.1 获取应用信息LoadedApk    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);    // 1.2、创建Application的Context    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);    // ......}

一、获取应用信息LoadedApk

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,        CompatibilityInfo compatInfo) {    return getPackageInfo(ai, compatInfo, null, false, true, false);}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,        ClassLoader baseLoader, boolean securityViolation, boolean includeCode,        boolean registerPackage) {    synchronized (mResourcesManager) {        WeakReference<LoadedApk> ref;        // 这里就可以看到,LoadedApk会缓存在mPackages中,如果为null,就会创建一个,之后就不需要创建了        if (includeCode) {            ref = mPackages.get(aInfo.packageName);        } else {            ref = mResourcePackages.get(aInfo.packageName);        }        LoadedApk packageInfo = ref != null ? ref.get() : null;        if (packageInfo == null || (packageInfo.mResources != null                && !packageInfo.mResources.getAssets().isUpToDate())) {            packageInfo =                new LoadedApk(this, aInfo, compatInfo, baseLoader,                        securityViolation, includeCode &&                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);            if (mSystemThread && "android".equals(aInfo.packageName)) {                packageInfo.installSystemApplicationInfo(aInfo,                        getSystemContext().mPackageInfo.getClassLoader());            }            if (includeCode) {                mPackages.put(aInfo.packageName,                        new WeakReference<LoadedApk>(packageInfo));            } else {                mResourcePackages.put(aInfo.packageName,                        new WeakReference<LoadedApk>(packageInfo));            }        }        return packageInfo;    }}

二、创建Application的Context

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");    // 直接创建一个ContextImpl对象    return new ContextImpl(null, mainThread,            packageInfo, null, null, false, null, null);}

/frameworks/base/core/java/android/app/ContextImpl.java

private ContextImpl(ContextImpl container, ActivityThread mainThread,        LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,        Display display, Configuration overrideConfiguration) {    mOuterContext = this;    mMainThread = mainThread;    mActivityToken = activityToken;    mRestricted = restricted;    if (user == null) {        user = Process.myUserHandle();    }    mUser = user;    mPackageInfo = packageInfo;    mResourcesManager = ResourcesManager.getInstance();    mDisplay = display;    mOverrideConfiguration = overrideConfiguration;    final int displayId = getDisplayId();    CompatibilityInfo compatInfo = null;    if (container != null) {        compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();    }    if (compatInfo == null && displayId == Display.DEFAULT_DISPLAY) {        compatInfo = packageInfo.getCompatibilityInfo();    }    mDisplayAdjustments.setCompatibilityInfo(compatInfo);    mDisplayAdjustments.setActivityToken(activityToken);    //packageInfo为LoadedApk对象,也就是这里调用了LoadedApk的getResources方法    Resources resources = packageInfo.getResources(mainThread);    if (resources != null) {        if (activityToken != null                || displayId != Display.DEFAULT_DISPLAY                || overrideConfiguration != null                || (compatInfo != null && compatInfo.applicationScale                        != resources.getCompatibilityInfo().applicationScale)) {            resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),                    packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),                    packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,                    overrideConfiguration, compatInfo, activityToken);        }    }    mResources = resources;    if (container != null) {        mBasePackageName = container.mBasePackageName;        mOpPackageName = container.mOpPackageName;    } else {        mBasePackageName = packageInfo.mPackageName;        ApplicationInfo ainfo = packageInfo.getApplicationInfo();        if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {            // Special case: system components allow themselves to be loaded in to other            // processes.  For purposes of app ops, we must then consider the context as            // belonging to the package of this process, not the system itself, otherwise            // the package+uid verifications in app ops will fail.            mOpPackageName = ActivityThread.currentPackageName();        } else {            mOpPackageName = mBasePackageName;        }    }    mContentResolver = new ApplicationContentResolver(this, mainThread, user);}

/frameworks/base/core/java/android/app/LoadedApk.java

public Resources getResources(ActivityThread mainThread) {    if (mResources == null) {        // 可以看到直接调用的是ActivityThread的getTopLevelResources方法        mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,                mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);    }    return mResources;}

/frameworks/base/core/java/android/app/ActivityThread.java

Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,        String[] libDirs, int displayId, Configuration overrideConfiguration,        LoadedApk pkgInfo) {    // 可以看到直接调用的是ResourcesManager的getTopLevelResources方法    return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,            displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);}
ActivityThread() {    mResourcesManager = ResourcesManager.getInstance();}

/frameworks/base/core/java/android/app/ResourcesManager.java

// ResourcesManager是一个单例类,也就是说只会有一份,所以我们所有资源的获取最终调用的都是这个对象public static ResourcesManager getInstance() {    synchronized (ResourcesManager.class) {        if (sResourcesManager == null) {            sResourcesManager = new ResourcesManager();        }        return sResourcesManager;    }}
原创粉丝点击